├── .gitignore ├── LICENSE ├── README.md ├── ap_config ├── README.md ├── ap_cli.py ├── cli_config_workflow.py ├── configurations │ ├── README.md │ ├── default-group-config.txt │ ├── enterprise-wpa3.txt │ ├── open-captive-portal.txt │ ├── open-network.txt │ └── psk-network.txt ├── media │ └── ap-flowchart.png └── requirements.txt ├── connected_clients ├── README.md ├── central_token.json ├── connected_clients.py ├── media │ └── script_terminal_output.png ├── requirements.txt └── site_names.json ├── detailed_central_device_inventory ├── README.md ├── central_token.json ├── detailed_central_device_inventory.py └── requirements.txt ├── device_inventory_migration ├── README.md ├── current_central_token.json ├── device_inventory_migration.py ├── device_list.json ├── media │ └── workflow_overview.png ├── new_central_token.json └── requirements.txt ├── device_onboarding ├── README.md ├── central_token.json ├── device_onboarding.py ├── device_templates │ ├── cx │ │ └── template.txt │ └── iap │ │ └── template.txt ├── media │ ├── script_terminal_output.gif │ └── workflow_overview.png ├── requirements.txt └── workflow_variables.json ├── device_provisioning ├── README.md ├── central_token.json ├── device_provisioning.py ├── device_templates │ ├── cx │ │ └── template.txt │ └── iap │ │ └── template.txt ├── media │ ├── script_terminal_output.gif │ └── workflow_overview.png ├── requirements.txt └── workflow_variables.json ├── inventory_to_excel ├── README.md ├── inventory.py ├── inventory_excel_workflow.py └── requirements.txt ├── msp_customer_deletion ├── README.md ├── central_token.json ├── media │ ├── script_terminal_output.gif │ └── workflow_overview.png ├── msp_customer_deletion.py ├── requirements.txt └── workflow_variables.json ├── msp_customer_onboarding ├── README.md ├── central_token.json ├── media │ ├── script_terminal_output_auto_licensing.gif │ ├── script_terminal_output_without_auto_subscription.gif │ └── workflow_overview.png ├── msp_customer_onboarding.py ├── requirements.txt ├── workflow_variables_auto_subscription.json └── workflow_variables_without_auto_subscription.json ├── renaming_aps ├── README.md ├── central_token.json ├── media │ └── script_terminal_output.gif ├── output.csv ├── renaming_aps.py ├── requirements.txt ├── variables.csv └── variables_sample.csv ├── streaming-api-client ├── README.md ├── input.json ├── lib │ ├── __init__.py │ ├── streamingExport.py │ └── utilities.py ├── proto │ ├── __init__.py │ ├── apprf.proto │ ├── apprf_pb2.py │ ├── audit.proto │ ├── audit_pb2.py │ ├── location.proto │ ├── location_pb2.py │ ├── monitoring.proto │ ├── monitoring_pb2.py │ ├── presence.proto │ ├── presence_pb2.py │ ├── security.proto │ ├── security_pb2.py │ ├── streaming.proto │ └── streaming_pb2.py ├── requirements.txt ├── simple_app.py └── wsclient_public.py ├── user_provisioning ├── README.md ├── central_token.json ├── requirements.txt ├── script_output.csv ├── user_list.csv ├── user_provisioning.py └── user_roles.json ├── webhooks └── python-webclient │ ├── README.md │ ├── central_webhook_client.py │ └── input_info.json └── wlan_config ├── README.md ├── configurations ├── README.md ├── basic_sample.yaml ├── delete_all.yaml ├── delete_sample.yaml ├── enhanced_captive.yaml ├── enterprise-network.yaml ├── open_network.yaml └── psk_network.yaml ├── create_ssid_workflow.py ├── delete_ssid_workflow.py ├── requirements.txt └── wlan.py /.gitignore: -------------------------------------------------------------------------------- 1 | */env/ -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2019 Aruba, a Hewlett Packard Enterprise company 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # central-python-workflows 2 | 3 | This repository contains Python based workflows & code samples that utilize [Aruba Central's automation capabilities](https://developer.arubanetworks.com/aruba-central/docs/aruba-central-extensibility) and the Python SDK [pycentral](https://pypi.org/project/pycentral/) 4 | 5 | ## Aruba Central REST APIs 6 | - [Device Provisioning](https://github.com/aruba/central-python-workflows/tree/main/device_provisioning) 7 | - Create a group (Template-based group) 8 | - Upload Configuration Template to Group 9 | - Move Devices to the newly created Group. 10 | - Create a Site 11 | - Move Devices to the newly created Site. 12 | - [Device Onboarding](https://github.com/aruba/central-python-workflows/tree/main/device_onboarding) 13 | - Assign Devices to Central Application Instance 14 | - Provide Devices with Central Subscriptions. 15 | - Create a template group (Template-based group) 16 | - Upload Configuration Template to Group 17 | - Move Devices to the newly created Group. 18 | - Create a Site 19 | - Move Devices to the newly created Site. 20 | - [MSP Customer Onboarding](https://github.com/aruba/central-python-workflows/tree/main/msp_customer_onboarding) 21 | - Create a customer account within the Greenlake MSP account 22 | - Install an Aruba Central instance in the customer account & set the default group. 23 | - Move & assign subscriptions to devices in the customer's Central Instance 24 | - Optional Steps 25 | - Create a Site in the customer's Central instance 26 | - Move Devices to the newly created Site. 27 | - [MSP Customer Deletion](https://github.com/aruba/central-python-workflows/tree/main/msp_customer_deletion) 28 | - Unassigns all devices & licenses within the customer's Aruba Central Instance. The devices & licenses will be moved back to the MSP's inventory. 29 | - Uninstall the customer's Aruba Central instance 30 | - Delete the customer's Greenlake Instance 31 | - [Inventory to Excel Workflows](https://github.com/aruba/central-python-workflows/tree/main/inventory_to_excel)\ 32 | This workflow creates excel files populated with device details from devices currently in inventory. 33 | - [AP CLI Workflows](https://github.com/aruba/central-python-workflows/tree/main/ap_config)\ 34 | Access point(AP) config workflows use direct command line interface(CLI) commands to configure APs in an Aruba Central group or directly to an AOS10 AP. 35 | - [WLAN Workflows](https://github.com/aruba/central-python-workflows/tree/main/wlan_config)\ 36 | This workflow can be used to create and manage WLANs in groups on an Aruba Central. 37 | - [Detailed Central Device Inventory](https://github.com/aruba/central-python-workflows/tree/main/detailed_central_device_inventory/)\ 38 | This workflow can be used to fetch additional details for device inventory in Aruba Central & export it as a CSV. 39 | - [Device Inventory Migration](https://github.com/aruba/central-python-workflows/tree/main/device_inventory_migration/) 40 | This workflow automates the migration of multiple devices between two Aruba Central accounts. 41 | - [User Provisioning](https://github.com/aruba/central-python-workflows/tree/main/user_provisioning)\ 42 | This workflow can be used to provision new users to HPE Greenlake and Aruba Central. 43 | - [Bulk Renaming of APs (with CSV)](https://github.com/aruba/central-python-workflows/tree/main/renaming_aps)\ 44 | This workflow can be used to rename access points in Aruba Central with a custom CSV upload of serial numbers and names. 45 | - [Connected Clients](https://github.com/aruba/central-python-workflows/tree/main/connected_clients) 46 | - Gather connected client information based on site name and time frame 47 | - Output csv files are generated and created within workflow folder 48 | - [Aruba Central Postman Collection](https://www.postman.com/hpe-aruba-networking/workspace/hpe-aruba-networking-central/overview)\ 49 | Postman is a popular tool used to test HTTP Requests to API endpoints. Aruba Central offers a [Postman collection](https://www.postman.com/hpe-aruba-networking/workspace/hpe-aruba-networking-central/collection/32717089-b3b1c3e4-7d04-4af1-be8c-e5c51e2453bb) and [Postman environment](https://www.postman.com/hpe-aruba-networking/workspace/hpe-aruba-networking-central/environment/30369652-60b80c56-ad11-40d3-a4a6-5cde71abf2e4?action=share&creator=32717089&active-environment=30369652-60b80c56-ad11-40d3-a4a6-5cde71abf2e4) that you can use to test REST APIs with Aruba Central. 50 | 51 | To manage REST APIs in Aruba Central, go to `MAINTAIN -> ORGANIZATION -> PLATFORM INTEGRATION -> REST API`.\ 52 | Learn more about Aruba Central REST APIs [here](https://developer.arubanetworks.com/aruba-central/docs/api-getting-started). 53 | 54 | ## Aruba Central Streaming API 55 | - [Streaming API Websocket Client Application](https://github.com/aruba/central-python-workflows/tree/main/streaming-api-client) 56 | The sample script in this section contains sample websocket client application based on python. 57 | The sample python script would establish a websocket connection and decode the google protobuf message to human readable format. 58 | 59 | To manage Streaming APIs in Aruba Central, go to `MAINTAIN -> ORGANIZATION -> PLATFORM INTEGRATION -> STREAMING`.\ 60 | Learn more about Aruba Central Streaming APIs [here](https://developer.arubanetworks.com/aruba-central/docs/streaming-api-getting-started). 61 | 62 | ## Aruba Central Webhooks 63 | 64 | - [Webhook Client application](https://github.com/aruba/central-python-workflows/tree/main/webhooks) 65 | The sample script in this section would start a HTTP(s) client to receive Alerts from Aruba Central via webhooks. 66 | 67 | To manage Webhooks in Aruba Central, go to `MAINTAIN -> ORGANIZATION -> PLATFORM INTEGRATION -> WEBHOOKS`.\ 68 | Learn more about Aruba Central Webhooks [here](https://developer.arubanetworks.com/aruba-central/docs/webhooks-getting-started). 69 | 70 | For more information about Aruba Central, [refer here](https://www.arubanetworks.com/techdocs/central/latest/content/home.htm) 71 | -------------------------------------------------------------------------------- /ap_config/README.md: -------------------------------------------------------------------------------- 1 | # AP Configuration Workflows 2 | 3 | Access point(AP) config workflows use direct command line interface(CLI) commands to configure APs in an Aruba Central group or directly to an AOS10 AP. 4 | 5 | This README presupposes general knowledge of how to use ArubaCentral API's and execute workflow scripts. Please see [here](https://github.com/aruba/pycentral/blob/master/README.md) 6 | for detailed information on installing pycentral and getting setup to execute workflow scripts. 7 | 8 | # Table of Contents 9 | - [AP Configuration Workflows](#ap-configuration-workflows) 10 | - [Table of Contents](#table-of-contents) 11 | - [Setup](#setup) 12 | - [How To Install](#how-to-install) 13 | - [CLI AP Config](#cli-ap-config) 14 | - [Workflow Functionality](#workflow-functionality) 15 | - [Configuration Setup](#configuration-setup) 16 | - [Executing The Workflow](#executing-the-workflow) 17 | - [Documentation](#documentation) 18 | - [Troubleshooting Issues](#troubleshooting-issues) 19 | - [Known Issues](#known-issues) 20 | 21 | 22 | # Setup 23 | 1. Clone this repository and ```cd``` into the workflow directory: 24 | ``` 25 | git clone https://github.com/aruba/central-python-workflows.git 26 | cd central-python-workflows/ap_config 27 | ``` 28 | 29 | 2. An authorization file containing credential information for your Aruba Central account is required to run workflows. The details and structure 30 | for how to create this can be found [here](https://github.com/aruba/pycentral/tree/master/sample_scripts). 31 | An example token only yaml file would look like this: 32 | ``` 33 | central_info: 34 | base_url: "" 35 | token: 36 | access_token: "" 37 | ssl_verify: true 38 | ``` 39 | 40 | The Central Authorization filename is set as a CLI argument to the workflow as shown below: 41 | ``` 42 | --central_auth <"filepath"> 43 | ``` 44 | 45 | 46 | # How To Install 47 | In order to run a workflow script please install the requirements. Pycentral must also be installed and is included in the requirements. Please refer [here](https://github.com/aruba/pycentral/blob/master/README.md) for more information on Pycentral. 48 | 49 | 1. install requirements.txt. Make sure python version 3 is installed in system. 50 | ``` 51 | $ pip install -r .\requirements.txt 52 | ``` 53 | 54 | Now you can start executing workflows. 55 | 56 | 57 | # CLI AP Config 58 | The cli_config_workflow merges and replaces existing AP CLI configurations with CLI input from a .txt file. 59 | 60 | ## Workflow Functionality 61 | 62 | 1. This workflow should be used to configure a Central group or specific AOS10 AP. 63 | 64 | 2. Workflow takes a .txt file as input with AP CLI commands to configure an AP. 65 | 66 | 3. Pulls existing configuration from a Central group or specific AOS10 AP. 67 | 68 | 4. Merges input CLI with existing configuration, replacing any existing configuration that matches a context from the input. Any input not replaced is added to the new configuration. 69 | 70 | 5. Posts the merged configuration to the target AP. 71 | 72 | 6. Pulls new configuration from Central and validates that input was posted. Any CLI input command not in the new configuration is printed to the terminal as an error. 73 | 74 | 7. Can optionally replace entire config by setting a flag during execution. 75 | 76 | ## Configuration Setup 77 | AP configuration is provided in a .txt file in CLI format. 78 | 79 | 1. Config .txt filepath needs to be set using the cli_path argument shown here: 80 | ``` 81 | --cli_path <"filepath"> 82 | ``` 83 | 84 | 2. The body structure for the input .txt file is purely AP CLI. Commands that need to be in a CLI context should be indented two spaces under the parent context. 85 | 86 | Here is an example of context switching with a WLAN profile: 87 | 88 | ``` 89 | wlan ssid-profile test 90 | essid test 91 | opmode enhanced-open 92 | type guest 93 | captive-portal internal 94 | dtim-period 1 95 | broadcast-filter arp 96 | max-authentication-failures 0 97 | blacklist 98 | inactivity-timeout 1000 99 | dmo-channel-utilization-threshold 90 100 | max-clients-threshold 1024 101 | enable 102 | utf8 103 | wlan access-rule test 104 | utf8 105 | rule any any match any any any permit 106 | ``` 107 | 108 | A directory of sample configurations has been provided as a reference in the configurations folder under the ap_config directory [here](https://github.com/aruba/central-python-workflows/tree/main/ap_config/configurations) 109 | 110 | ## Executing The Workflow 111 | 1. With the input file configured the workflow can now be executed. 112 | 113 | ``` 114 | $ python replace_ap_workflow.py --central_auth <"/central/token/path"> --cli_path <"config/path"> 115 | ``` 116 | 117 | Workflow can also be executed with the -r flag to completely replace the existing configuration with the input. 118 | ``` 119 | $ python replace_ap_workflow.py -r --central_auth <"/central/token/path"> --cli_path <"config/path"> 120 | ``` 121 | 122 | 123 | # Documentation 124 | * **Python package documentation:** [pycentral module documentation](https://pycentral.readthedocs.io/en/latest/) 125 | * **Use-Cases and Workflows:** [Aruba Developer Hub](https://developer.arubanetworks.com/aruba-central) 126 | * **AP CLI Config Reference:** [API DevHub Reference](https://developer.arubanetworks.com/aruba-central/reference/apiap_clisupdate_configuration_clis) 127 | * **Get AP CLI Config Reference:** [Get AP CLI Config Reference](https://developer.arubanetworks.com/aruba-central/reference/apiap_clisget_configuration_clis) 128 | * **AP CLI Reference Guide:** [CLI Reference](https://www.arubanetworks.com/techdocs/AOS_10.x_Books/AOS10_CLI_Guide.pdf) 129 | 130 | # Troubleshooting Issues 131 | 1. If you encounter module import errors, make sure that the package has been installed correctly. 132 | 2. Devices on operating systems older than AOS10 cannot use serial number as target value. 133 | 3. Check that input commands are compatible with device version. 134 | 4. Ensure Indentation is correct for context switching. The workflow uses regex pattern matching based on appropriate whitespace for merging and copying commands. 135 | 136 | # Known Issues 137 | 1. Devices on operating systems older than AOS10 cannot use serial number as target value. 138 | -------------------------------------------------------------------------------- /ap_config/ap_cli.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from pycentral.configuration import ApConfiguration as ap 24 | import copy 25 | import sys 26 | import re 27 | 28 | 29 | class ApCLIConfig(object): 30 | """ 31 | Contains functions to manage Aruba Central Access Points via CLI. 32 | """ 33 | 34 | def get_ap_config(self, conn, group_name): 35 | """ 36 | Get whole configuration in CLI format of an UI group or AOS10 device. 37 | 38 | :param conn: Instance of class:`pycentral.ArubaCentralBase`. 39 | :type conn: class:`pycentral.ArubaCentralBase` 40 | :param group_name: Central UI groupname or serial for AOS10 device. 41 | :type group_name: str 42 | 43 | :return: List of strings in CLI format of AP configuration 44 | :rtype: list 45 | """ 46 | 47 | # Call API 48 | resp = ap.get_ap_config(self, conn, group_name) 49 | if resp["code"] != 200: 50 | sys.exit( 51 | "Bad request for get_ap_config() response code: %d. " 52 | "%s. Exiting..." % resp["code"], resp["msg"]["description"]) 53 | else: 54 | print("Configuration loaded successfully from %s" 55 | % group_name) 56 | 57 | return resp["msg"] 58 | 59 | def merge_config(self, current, input): 60 | """ 61 | Combine current AP configuration with additional configurations. 62 | the return value of get_ap_config() should be used for the current 63 | parameter to avoid corrupting the configuration. Matching contexts 64 | are replaced with input commands. Any input not matched in current 65 | is added. 66 | 67 | :param current: Current AP CLI config for a Central group. List of 68 | strings in CLI format. 69 | :type param: List 70 | :param input: AP CLI commands to add/replace over current. List of 71 | strings in CLI format. 72 | :type input: List 73 | 74 | :return: Merged list of strings from current and input. 75 | :rtype: List 76 | """ 77 | 78 | # Setup values 79 | input = copy.deepcopy(input) 80 | result = [] 81 | next_block = 0 82 | regex = re.compile('\\S') 83 | 84 | for line in range(len(current)): 85 | # Skip to next block if a context was replaced. 86 | if line < next_block: 87 | continue 88 | if current[line] in input: 89 | # Replace current context block with input from new CLI. 90 | if regex.match(current[line]) is not None: 91 | next_block = self.get_next_context(current, line) 92 | result.append(current[line]) 93 | input = self.copy_context(input, current[line], result) 94 | else: 95 | result.append(current[line]) 96 | 97 | # Add unmatched commands. 98 | for line in input: 99 | result.append(line) 100 | 101 | return result 102 | 103 | def replace_config(self, conn, group_name, cli_config): 104 | """ 105 | Replace whole configuration of a Central UI group. Configuration is 106 | in CLI format as a list of strings. 107 | 108 | :param conn: Instance of class:`pycentral.ArubaCentralBase`. 109 | :type conn: class:`pycentral.ArubaCentralBase` 110 | :param group_name: Central UI groupname or serial for AOS10 device. 111 | :type group_name: str 112 | :param cli_config: CLI commands for AP configuration. 113 | :type cli_config: list of strings. 114 | """ 115 | 116 | resp = ap.replace_ap(self, conn, group_name, cli_config) 117 | if resp["code"] != 200: 118 | sys.exit( 119 | "Bad request for get_ap_config() response code: %d. " 120 | "%s. Exiting..." % resp["code"], resp["msg"]["description"]) 121 | else: 122 | print("Configuration posted at %s" % group_name) 123 | 124 | return resp["msg"] 125 | 126 | def get_next_context(self, cli, index): 127 | """ 128 | Finds the index of the start of the next context in a list of CLI 129 | commands. 130 | 131 | :param cli: A list of AP CLI commands. 132 | :type cli_config: list of strings. 133 | :param index: Starting index for cli parameter. 134 | :type index: int 135 | 136 | :return: index of the next CLI context, or None if no other 137 | context in list. 138 | :rtype: int/None 139 | """ 140 | 141 | # Check for out of bounds. 142 | if index + 1 > len(cli): 143 | return 144 | 145 | regex = re.compile('\\s\\s\\S') 146 | 147 | for i in range(index + 1, len(cli)): 148 | if regex.match(cli[i]) is None: 149 | return i 150 | 151 | return 0 152 | 153 | def copy_context(self, cli, context, result): 154 | """ 155 | Copy the commands of a CLI context into an array. 156 | 157 | :param cli: A list of AP CLI commands. 158 | :type cli_config: list of strings. 159 | :param context: CLI context string to copy child commands from. 160 | :type context: str 161 | :param result: result list to append commands to. 162 | :type result: list of strings. 163 | 164 | :return: modified cli list with copied commands removed. 165 | :rtype: list 166 | """ 167 | 168 | index = cli.index(context) 169 | regex = re.compile('\\s\\s\\S') 170 | next = self.get_next_context(cli, index) 171 | 172 | # Check for out of bounds. 173 | if index + 1 > len(cli): 174 | return 175 | 176 | # Copy until next context. 177 | for i in range(index + 1, len(cli)): 178 | if regex.match(cli[i]) is None: 179 | break 180 | result.append(cli[i]) 181 | 182 | # Clean up input. 183 | del cli[index:next] 184 | return cli 185 | -------------------------------------------------------------------------------- /ap_config/cli_config_workflow.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | 5 | """ 6 | Workflow replaces existing Central AP configurations with input from a .txt 7 | file. This includes creation of an ArubaCentralBase instance through the 8 | usage of a config file, which is required for pycentral API usage. 9 | Configuration file should contain new AP configuration in CLI format. Please 10 | refer to the README for full details. 11 | """ 12 | from pycentral.workflows.workflows_utils import get_conn_from_file 13 | from ap_cli import ApCLIConfig 14 | from argparse import ArgumentParser 15 | from colorama import Fore, Style, init 16 | import sys 17 | import os 18 | 19 | 20 | def main(): 21 | 22 | args = define_arguments() 23 | 24 | # Create ArubaCentralBase Instance. 25 | central = get_conn_from_file(args.central_auth) 26 | 27 | # Setup values 28 | with open(args.cli_path) as in_file: 29 | input_cli = in_file.read().splitlines() 30 | target = args.ap 31 | ap = ApCLIConfig() 32 | 33 | if not args.r: 34 | # Get existing CLI. 35 | ap_cli = ap.get_ap_config(central, target) 36 | # Merge CLI with input, format data for post. 37 | post_data = {"clis": ap.merge_config(ap_cli, input_cli)} 38 | # Post merged config to target. 39 | ap.replace_config(central, target, post_data) 40 | else: 41 | post_data = {"clis": input_cli} 42 | ap.replace_config(central, target, post_data) 43 | 44 | # Initialize colorama. 45 | init() 46 | # Setup validation values. 47 | print(Fore.GREEN + "Validating posted configuration..." + Style.RESET_ALL) 48 | updated_config = ap.get_ap_config(central, target) 49 | debug_list = [] 50 | 51 | for line in input_cli: 52 | if (line not in updated_config) and ('passphrase' not in line): 53 | debug_list.append(line) 54 | 55 | if len(debug_list) > 0: 56 | print(Fore.RED + "Error, some commands not posted successfully:") 57 | for line in debug_list: 58 | print(" " + Fore.RED + line) 59 | else: 60 | print(Fore.GREEN + " All configurations posted successfully!") 61 | 62 | 63 | def define_arguments(): 64 | """ 65 | This function defines command line arguments that can be used with this 66 | workflow. 67 | 68 | :return: Argparse namespace with central auth filepath and ssid config 69 | filepath. 70 | :type return: argparse.Namespace 71 | """ 72 | 73 | description = "This workflow replaces existing AP CLI configurations "\ 74 | "to an Aruba Central group. If no current context matches input "\ 75 | "commands, the new commands will be added to existing configuration." 76 | 77 | parser = ArgumentParser(description=description) 78 | 79 | parser.add_argument('ap', metavar='target', type=str, 80 | help=('Central groupname or AOS10 AP serial')) 81 | parser.add_argument('-r', help="Replace entire configuration", 82 | action='store_true') 83 | parser.add_argument('--central_auth', default='central_token.yaml', 84 | help=('Central Credential auth filepath')) 85 | parser.add_argument('--cli_path', help=('CLI config filepath'), 86 | required=True, type=validate_path) 87 | return parser.parse_args() 88 | 89 | 90 | def validate_path(path): 91 | """ 92 | Validates input for config CLI argument. 93 | 94 | :param path: file path for CLI configuration file. 95 | :return: path 96 | """ 97 | 98 | if not os.path.exists(path): 99 | sys.exit("Invalid file path for config_path argument. Exiting...") 100 | 101 | return path 102 | 103 | 104 | if __name__ == "__main__": 105 | main() 106 | -------------------------------------------------------------------------------- /ap_config/configurations/README.md: -------------------------------------------------------------------------------- 1 | # Sample CLI Configurations 2 | 3 | The files in this directory are sample CLI configurations to demonstrate structure and usage examples. 4 | 5 | ### default-group-config 6 | 7 | Configuration of a new Aruba Central group with default settings. 8 | 9 | ### WLAN Profiles 10 | 1. Generic Open Network 11 | - Security level open 12 | - Open key management 13 | 2. Captive portal 14 | - Security level visitors - captive portal 15 | - External captive portal 16 | - Enhanced open key management 17 | 3. WPA3 PSK network 18 | - Personal security level 19 | - WPA3 personal key management 20 | 4. WPA3 Enterprise network 21 | - Security level enterprise 22 | - WPA3 CCM128 key management -------------------------------------------------------------------------------- /ap_config/configurations/default-group-config.txt: -------------------------------------------------------------------------------- 1 | enet0-port-profile default_wired_port_profile 2 | hash-mgmt-password 3 | hash-mgmt-user admin password hash ******** 4 | wlan access-rule default_wired_port_profile 5 | index 1 6 | rule any any match any any any permit 7 | wlan access-rule wired-SetMeUp 8 | index 2 9 | rule masterip 0.0.0.0 match tcp 80 80 permit 10 | rule masterip 0.0.0.0 match tcp 4343 4343 permit 11 | rule any any match udp 67 68 permit 12 | rule any any match udp 53 53 permit 13 | wlan external-captive-portal 14 | server localhost 15 | url \"/\" 16 | auth-text \"Authenticated\" 17 | port 80 18 | auto-whitelist-disable 19 | https 20 | ids 21 | wireless-containment none 22 | wired-port-profile default_wired_port_profile 23 | no shutdown 24 | switchport-mode trunk 25 | allowed-vlan all 26 | native-vlan ap-ip-vlan 27 | access-rule-name default_wired_port_profile 28 | speed auto 29 | duplex full 30 | type employee 31 | captive-portal disable 32 | inactivity-timeout 1000 33 | port-bonding 34 | wired-port-profile wired-SetMeUp 35 | no shutdown 36 | switchport-mode access 37 | allowed-vlan all 38 | native-vlan guest 39 | access-rule-name wired-SetMeUp 40 | speed auto 41 | duplex auto 42 | type guest 43 | captive-portal disable 44 | inactivity-timeout 1000 45 | uplink 46 | preemption 47 | enforce none 48 | failover-internet-pkt-lost-cnt 10 49 | failover-internet-pkt-send-freq 30 50 | failover-vpn-timeout 180 51 | enet0-port-profile default_wired_port_profile 52 | blacklist-time 3600 53 | auth-failure-blacklist-time 3600 54 | auth-survivability cache-time-out 24 55 | rf-band all 56 | extended-ssid 57 | syslog-level warn ap-debug 58 | syslog-level warn network 59 | syslog-level warn security 60 | syslog-level warn system 61 | syslog-level warn user 62 | syslog-level warn user-debug 63 | syslog-level warn wireless 64 | clock timezone none 0 0 65 | terminal-access 66 | deny-local-routing 67 | cp-cert-checksum 4b625464fd509d449e24e4c3c9fd6cc0 68 | enable-automatic-placement 69 | cluster-security 70 | allow-low-assurance-devices -------------------------------------------------------------------------------- /ap_config/configurations/enterprise-wpa3.txt: -------------------------------------------------------------------------------- 1 | wlan ssid-profile enterprise-test 2 | essid enterprise-test 3 | opmode wpa3-aes-ccm-128 4 | type employee 5 | captive-portal disable 6 | dtim-period 1 7 | broadcast-filter arp 8 | inactivity-timeout 1000 9 | max-authentication-failures 0 10 | blacklist 11 | dmo-channel-utilization-threshold 90 12 | max-clients-threshold 64 13 | enable 14 | utf8 15 | wlan access-rule enterprise-test 16 | utf8 17 | rule any any match any any any deny -------------------------------------------------------------------------------- /ap_config/configurations/open-captive-portal.txt: -------------------------------------------------------------------------------- 1 | wlan ssid-profile captive-open 2 | essid captive-open 3 | opmode enhanced-open 4 | type guest 5 | captive-portal external 6 | dtim-period 1 7 | broadcast-filter arp 8 | max-authentication-failures 0 9 | blacklist 10 | inactivity-timeout 1000 11 | dmo-channel-utilization-threshold 90 12 | max-clients-threshold 1024 13 | enable 14 | utf8 15 | auth-server InternalServer 16 | wlan access-rule captive-open 17 | utf8 18 | rule any any match any any any permit -------------------------------------------------------------------------------- /ap_config/configurations/open-network.txt: -------------------------------------------------------------------------------- 1 | wlan ssid-profile open-network 2 | essid open-network 3 | opmode opensystem 4 | type employee 5 | captive-portal disable 6 | dtim-period 1 7 | broadcast-filter arp 8 | inactivity-timeout 1000 9 | max-authentication-failures 0 10 | blacklist 11 | dmo-channel-utilization-threshold 90 12 | max-clients-threshold 64 13 | enable 14 | utf8 15 | wlan access-rule open-network 16 | utf8 17 | rule any any match any any any permit -------------------------------------------------------------------------------- /ap_config/configurations/psk-network.txt: -------------------------------------------------------------------------------- 1 | wlan ssid-profile psk-network 2 | essid psk-network 3 | opmode wpa3-sae-aes 4 | wpa-passphrase password 5 | type employee 6 | captive-portal disable 7 | dtim-period 1 8 | broadcast-filter arp 9 | inactivity-timeout 1000 10 | max-authentication-failures 0 11 | blacklist 12 | dmo-channel-utilization-threshold 90 13 | max-clients-threshold 64 14 | enable 15 | utf8 16 | auth-server InternalServer 17 | wlan access-rule psk-network 18 | utf8 19 | rule any any match any any any permit -------------------------------------------------------------------------------- /ap_config/media/ap-flowchart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/ap_config/media/ap-flowchart.png -------------------------------------------------------------------------------- /ap_config/requirements.txt: -------------------------------------------------------------------------------- 1 | pycentral==1.4.1 2 | colorama==0.4.6 -------------------------------------------------------------------------------- /connected_clients/README.md: -------------------------------------------------------------------------------- 1 | # Connected Clients 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) library to achieve the following steps on an HPE Aruba Networking Central account- 3 | 1. Gather connected client information based on site name and time frame 4 | 2. Output csv files are generated and created within workflow folder 5 | 6 | ## Guide 7 | A comprehensive guide has been made for this workflow and can be referenced [here](https://developer.arubanetworks.com/hpe-aruba-networking-central/docs/connected-clients) on our HPE Aruba Networking Developer Hub 8 | 9 | ## Prerequisites 10 | 1. Connected Clients need to be online and connected 11 | 12 | ## Installation Steps 13 | In order to run the script, please complete the steps below: 14 | 1. Clone this repository and `cd` into the workflow directory: 15 | ```bash 16 | git clone https://github.com/aruba/central-python-workflows 17 | cd central-python-workflows/connected_clients 18 | ``` 19 | 20 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 21 | ```bash 22 | python -m venv env 23 | ``` 24 | 25 | 3. Activate the virtual environment 26 | In Mac/Linux: 27 | ```bash 28 | source env/bin/activate 29 | ``` 30 | In Windows: 31 | ```bash 32 | env/Scripts/activate.bat 33 | ``` 34 | 35 | 4. Install the packages required for the script 36 | ```bash 37 | python -m pip install -r requirements.txt 38 | ``` 39 | 40 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 41 | ```json 42 | { 43 | "central_info": { 44 | "base_url": "", 45 | "token": { 46 | "access_token": "" 47 | } 48 | }, 49 | "ssl_verify": true 50 | } 51 | ``` 52 | **Note** 53 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 54 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 55 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 56 | 57 | 6. Provide a one or more site names into the string list array in the [site_names.json](site_names.json) 58 | ```json 59 | { 60 | "site_names": [ 61 | "", 62 | "" 63 | ] 64 | } 65 | ``` 66 | 7. The default timeframes preset within this script are 3 hours, 24 hours, 1 week, and 1 month. The "timeframe" list variable within the connected_clients.py file is responsible for using all of those preset variables. If you would only like the see connected clients that connected last within just one week, you can make one_week_ago the only item within the "timeframe" list variable. Otherwise if no changes are made, the connected_clients.py script will output the 4 default timeframes. 67 | ```bash 68 | # timeframe = [one_day_ago, one_week_ago] 69 | # timeframe = [one_week_ago] 70 | # timeframe = [one_month_ago] 71 | timeframe = [three_hours_ago, one_day_ago, one_week_ago, one_month_ago] 72 | ``` 73 | 74 | 8. Once **central_token.json** & **site_names.json** are updated with the relevant information, you can execute the script with the following command: 75 | ```bash 76 | python connected_clients.py 77 | ``` 78 | **Note** 79 | - This script takes the following optional parameter to overide central auth file name 80 | - central_auth - Path of Central Token File 81 | - You can run the following command to use the optional parameter - 82 | ```bash 83 | python connected_clients.py --central_auth 84 | ``` 85 | 86 | 9. If the script runs successfully, your terminal output should look like this - 87 |

88 | 89 |

90 | 91 | 10. Depending on the site name and time frame inputs, one or more output csv files will be created with the output of the script results 92 | - Columns will consist of: 'Client Username', 'Client IP Address', 'Client MAC Address', 'Association Time', 'AP Name', 'Site Name' 93 | ```csv 94 | Generated:,2024-08-01 16:45:00.730098 95 | Report By:,Site 96 | Site Name:,Roseville Admin Building 97 | Reporting Period:,"30 days, 0:00:00" 98 | "" 99 | Client Username,Client IP Address,Client MAC Address,Association Time,AP Name,Site Name 100 | --,192.168.0.198,dc:a6:32:a2:aa:7a,2024-08-01 15:28:30,Automation-Central-01,Roseville Admin Building 101 | ``` 102 | 103 | ## Central APIs used for this workflow - 104 | 1. [List Connected Wireless Clients](https://developer.arubanetworks.com/hpe-aruba-networking-central/reference/apiexternal_controllerget_wireless_clients) 105 | 2. [List Connected Wired Clients](https://developer.arubanetworks.com/hpe-aruba-networking-central/reference/apiexternal_controllerget_wired_clients) -------------------------------------------------------------------------------- /connected_clients/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } 10 | -------------------------------------------------------------------------------- /connected_clients/media/script_terminal_output.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/connected_clients/media/script_terminal_output.png -------------------------------------------------------------------------------- /connected_clients/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | colored==2.2.3 5 | halo==0.0.31 6 | idna==3.7 7 | pycentral==1.4.1 8 | PyYAML==6.0.1 9 | requests==2.32.2 10 | six==1.16.0 11 | spinners==0.0.24 12 | termcolor==2.3.0 13 | urllib3==2.2.2 14 | -------------------------------------------------------------------------------- /connected_clients/site_names.json: -------------------------------------------------------------------------------- 1 | { 2 | "site_names": [ 3 | "", 4 | "" 5 | ] 6 | } 7 | -------------------------------------------------------------------------------- /detailed_central_device_inventory/README.md: -------------------------------------------------------------------------------- 1 | # Detailed Central Device Inventory 2 | 3 | Currently, HPE Greenlake Cloud Platform provides users with the ability to export device inventory details in the form of a CSV file. Users sometimes require application-level(Aruba Central) details of devices like site details. This workflow leverages Central APIs & [Pycentral](https://pypi.org/project/pycentral/) to help you get this information. After exporting the device inventory CSV from HPE GLCP, you can run this script to get the following details of the devices in a CSV format. The CSV will have the following fields for each device in the device inventory for Standard Enterprise accounts - 4 | * Serial Number 5 | * Device Model 6 | * Mac Address 7 | * Part Number 8 | * Device Type 9 | * Subscription Key 10 | * Subscription Tier 11 | * Subscription Expiration 12 | * Archived 13 | * Application Customer Id 14 | * Ccs Region 15 | * For devices assigned to Sites, the following fields will be added 16 | * Site_name 17 | * Address 18 | * City 19 | * Latitude 20 | * Longitude 21 | * Site_id 22 | * State 23 | * Country 24 | * Zipcode 25 | 26 | For devices in an MSP account, an additional field called *Account name* would be present indicating the customer in which the device is assigned to. 27 | 28 | This script is just a starting point on the device details that you can get for devices from Aruba Central. Please feel free to modify the script to fetch and export additional details that are needed for your specific use-case. If you would like to share your modifications with our developer community, please raise a pull request with the modifications in this repository. 29 | 30 | ## Prerequisite 31 | 1. Device Inventory CSV generated from HPE Greenlake Cloud Platform should not be modified in any manner. 32 | 33 | ## Installation Steps 34 | In order to run the script, please complete the steps below: 35 | 1. Clone this repository and `cd` into the workflow directory: 36 | ```bash 37 | git clone https://github.hpe.com/hpe/central-python-workflows 38 | cd central-python-workflows/detailed_central_device_inventory/ 39 | ``` 40 | 41 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 42 | ```bash 43 | python -m venv env 44 | ``` 45 | 46 | 3. Activate the virtual environment 47 | In Mac/Linux: 48 | ```bash 49 | source env/bin/activate 50 | ``` 51 | In Windows: 52 | ```bash 53 | env/Scripts/activate.bat 54 | ``` 55 | 56 | 4. Install the packages required for the script 57 | ```bash 58 | python -m pip install -r requirements.txt 59 | ``` 60 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 61 | ```json 62 | { 63 | "central_info": { 64 | "base_url": "", 65 | "token": { 66 | "access_token": "" 67 | } 68 | }, 69 | "ssl_verify": true 70 | } 71 | ``` 72 | **Note** 73 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 74 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 75 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 76 | 6. The second file that is required for the script is the Device Inventory CSV from HPE Greenlake Platform. You can find the steps to get this device inventory CSV from the HPE GreenLake Edge to Cloud Platform User Guide [here](https://support.hpe.com/hpesc/public/docDisplay?docId=a00120892en_us&page=GUID-EB0B67B7-6FB3-423A-A6A6-FAEDE9FC3C4E.html). Once you have the CSV added it to the workflow's directory. 77 | **Note** 78 | Please don't make any changes to the columns in the **Device Inventory Details** section as this could cause errors in the script's execution. 79 | 80 | 1. Once **central_token.json** & device inventory CSV are updated with the relevant information, you can execute the script using the following command - 81 | ```bash 82 | python detailed_central_device_inventory.py --device_inventory_csv --export_csv_name 83 | ``` 84 | **Note** 85 | - This script takes the following optional parameters to overide default filenames for the script 86 | - central_auth - Path of Central Token File 87 | - device_inventory_csv - Path of Device Inventory CSV from HPE Greenlake Platform 88 | - export_csv_name - Path of Detailed Device Inventory CSV that the script should create after execution 89 | 90 | ## Central APIs used for this workflow 91 | 1. [List Sites](https://developer.arubanetworks.com/aruba-central/reference/sitesexternal_controllerget_sites) 92 | 2. [Get list of customers under the MSP account](https://developer.arubanetworks.com/aruba-central/reference/apiviewsmsp_apiget_customers) 93 | 3. [List Access Points](https://developer.arubanetworks.com/aruba-central/reference/apiexternal_controllerget_aps_v2) 94 | 4. [List Switches](https://developer.arubanetworks.com/aruba-central/reference/apiexternal_controllerget_switches) 95 | 5. [List Gateways](https://developer.arubanetworks.com/aruba-central/reference/apiexternal_controllerget_gateways) 96 | 97 | ## Note 98 | This Python script was developed and tested on Central version 2.5.7 99 | -------------------------------------------------------------------------------- /detailed_central_device_inventory/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /detailed_central_device_inventory/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | halo==0.0.31 5 | idna==3.7 6 | log-symbols==0.0.14 7 | pycentral==1.4.1 8 | PyYAML==6.0.1 9 | requests==2.31.0 10 | six==1.16.0 11 | spinners==0.0.24 12 | termcolor==2.3.0 13 | urllib3==2.2.2 -------------------------------------------------------------------------------- /device_inventory_migration/README.md: -------------------------------------------------------------------------------- 1 | # Device Inventory Migration 2 | 3 | Some of our customers may be managing multiple instances of Central. In such a scenario, they may sometimes have to move devices between instances of Central. Its possible to do this through the the GLCP & Central User Interface and via Central APIs. When multiple devices have to be moved between accounts, this can lead to the customer have to click through multiple lot of clicks has to be done for multiple devices, this workflow could result in multiple clicks. This makes the workflow prone to accidental clicks and human error. 4 | 5 | The script in this workflow automates the above process by using [Pycentral](https://pypi.org/project/pycentral/) library to do the following steps - 6 | In the **current** Central Account - 7 | 1. Unassign Central Subscriptions from Device(s) 8 | 2. Archive Device(s) 9 | 3. Unarchive Device(s) 10 | After the above steps are completed in the **current** Central account, then in the **new** Central account - 11 | 1. Add Device(s) 12 | 2. Assign Central Subscription to Device(s) 13 | 14 | 15 | **Note** - Throughout this README & the script - 16 | 1. **current** - This refers to the Central account from which devices have to be migrated from 17 | 2. **new** - This refers to the Central account to which devices have to be migrated into 18 | 19 | 20 | ![Demo Workflow](media/workflow_overview.png) 21 | 22 | ## Prerequisite 23 | 1. Device(s) in the current Central account have Central Subscriptions associated with them 24 | 2. The new Central account's subscription inventory has available seats in the same Central subscription tier that the devices are subscribed to in the current Central account. 25 | 26 | ## Installation Steps 27 | In order to run the script, please complete the steps below: 28 | 1. Clone this repository and `cd` into the workflow directory: 29 | ```bash 30 | git clone https://github.hpe.com/hpe/central-python-workflows 31 | cd central-python-workflows/device_inventory_migration/ 32 | ``` 33 | 34 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 35 | ```bash 36 | python -m venv env 37 | ``` 38 | 39 | 3. Activate the virtual environment 40 | In Mac/Linux: 41 | ```bash 42 | source env/bin/activate 43 | ``` 44 | In Windows: 45 | ```bash 46 | env/Scripts/activate.bat 47 | ``` 48 | 49 | 4. Install the packages required for the script 50 | ```bash 51 | python -m pip install -r requirements.txt 52 | ``` 53 | 5. Provide the Central API Gateway Base URL & Access Token in the [current_central_token.json](current_central_token.json) and [new_central_token.json](new_central_token.json) for both the Current & New Central Account Instances. 54 | ```json 55 | { 56 | "central_info": { 57 | "base_url": "", 58 | "token": { 59 | "access_token": "" 60 | } 61 | }, 62 | "ssl_verify": true 63 | } 64 | ``` 65 | **Note** 66 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 67 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 68 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 69 | 6. *(Optional)* You can skip this step if you are migrating all devices from the current Central account to the new Central account. Update the placeholder data of device details in [device_list.json](device_list.json). Please provide the serial numbers of the devices you would like to migrate 70 | ```json 71 | { 72 | "device_list": [ 73 | "", 74 | "" 75 | ] 76 | } 77 | ``` 78 | 7. Once **central_token.json** & **device_list.json** are updated with the relevant information, you can execute the script. 79 | 1. If you would like migrate all devices in the current Central account run this command: 80 | ```bash 81 | python device_inventory_migration.py --all_devices 82 | ``` 83 | 2. If you would like to migrate some devices from the current Central account run this command: 84 | ```bash 85 | python device_inventory_migration.py --device_list device_list.json 86 | ``` 87 | **Note** 88 | - This script takes the following optional parameters to overide default filenames for the script 89 | - current_central_auth - Path of Central Token File of Current Central Account 90 | - new_central_auth - Path of Central Token File of New Central Account 91 | - device_list - Path of Device List File 92 | 93 | ## Central APIs used for this workflow 94 | 1. [Get devices from device inventory](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryget_devices) 95 | 2. [Unassign subscription to a device](https://developer.arubanetworks.com/aruba-central/reference/acp_servicelicensewebviewsadmin_licenseapigw_unassign_licenses-1) 96 | 3. [Archive devices using Serial list](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryarchive_devices) 97 | 4. [Unarchive devices using Serial list](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryunarchive_devices) 98 | 5. [Add device using Mac and Serial number](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryadd_device) 99 | 6. [Assign subscription to a device](https://developer.arubanetworks.com/aruba-central/reference/acp_servicelicensewebviewsadmin_licenseapigw_assign_licenses-1) 100 | 101 | ## Note 102 | This Python script was tested on Central version 2.5.7 103 | -------------------------------------------------------------------------------- /device_inventory_migration/current_central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /device_inventory_migration/device_list.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_list": [ 3 | "", 4 | "" 5 | ] 6 | } -------------------------------------------------------------------------------- /device_inventory_migration/media/workflow_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/device_inventory_migration/media/workflow_overview.png -------------------------------------------------------------------------------- /device_inventory_migration/new_central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /device_inventory_migration/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | halo==0.0.31 5 | idna==3.7 6 | log-symbols==0.0.14 7 | pycentral==1.4.1 8 | PyYAML==6.0.1 9 | requests==2.31.0 10 | six==1.16.0 11 | spinners==0.0.24 12 | termcolor==2.3.0 13 | urllib3==2.2.2 14 | -------------------------------------------------------------------------------- /device_onboarding/README.md: -------------------------------------------------------------------------------- 1 | # Device Onboarding 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) library to achieve the following steps on an Aruba Central account- 3 | 1. Assign Devices to Central Application Instance 4 | 2. Provide Devices with Central Subscriptions. 5 | 3. Create a template group (Template-based group) 6 | 4. Upload Configuration Template to Group 7 | 5. Move Devices to the newly created Group. 8 | 6. Create a Site 9 | 7. Move Devices to the newly created Site. 10 | 11 | ![Demo Workflow](media/workflow_overview.png) 12 | 13 | ## Prerequisite 14 | 1. The Aruba Central application is installed in the Greenlake account in which the devices are present. 15 | 2. The devices used in the workflow are not assigned to any application in the Greenlake account and do not have any subscriptions associated with them. 16 | 3. The subscription that the workflow utilizes is not expired and has open seats for assignment. 17 | 4. The group and site that the workflow creates does not already exist in the Central account. 18 | 19 | ## Installation Steps 20 | In order to run the script, please complete the steps below: 21 | 1. Clone this repository and `cd` into the workflow directory: 22 | ```bash 23 | git clone https://github.com/aruba/central-python-workflows 24 | cd central-python-workflows/device_onboarding 25 | ``` 26 | 27 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 28 | ```bash 29 | python -m venv env 30 | ``` 31 | 32 | 3. Activate the virtual environment 33 | 34 | In Mac/Linux: 35 | ```bash 36 | source env/bin/activate 37 | ``` 38 | In Windows: 39 | ```bash 40 | env/Scripts/activate.bat 41 | ``` 42 | 4. Install the packages required for the script 43 | ```bash 44 | python -m pip install -r requirements.txt 45 | ``` 46 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 47 | ```json 48 | { 49 | "central_info": { 50 | "base_url": "", 51 | "token": { 52 | "access_token": "" 53 | } 54 | }, 55 | "ssl_verify": true 56 | } 57 | ``` 58 | **Note** 59 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 60 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 61 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 62 | 6. Update the placeholder data of Group, Site & Device details in [workflow_variables.json](workflow_variables.json) to match your environment. 63 | ```json 64 | { 65 | "device_details": { 66 | "SWITCH": { 67 | "": { 68 | "mac_address": "", 69 | "central_subscription": "" 70 | }, 71 | "": { 72 | "mac_address": "", 73 | "central_subscription": "" 74 | } 75 | }, 76 | "IAP": { 77 | "": { 78 | "mac_address": "", 79 | "central_subscription": "" 80 | } 81 | } 82 | }, 83 | "group_details": { 84 | "name": "", 85 | "attributes": { 86 | "template_info": { 87 | "Wired": true, 88 | "Wireless": true 89 | }, 90 | "group_properties": { 91 | "AllowedDevTypes": [ 92 | "AccessPoints", 93 | "Switches" 94 | ], 95 | "Architecture": "Instant", 96 | "ApNetworkRole": "Standard", 97 | "AllowedSwitchTypes": [ 98 | "AOS_CX" 99 | ] 100 | } 101 | }, 102 | "config_templates": { 103 | "CX": { 104 | "template_name": "", 105 | "template_filename": "", 106 | "version": "", 107 | "model": "" 108 | }, 109 | "IAP": { 110 | "template_name": "", 111 | "template_filename": "", 112 | "version": "", 113 | "model": "" 114 | } 115 | } 116 | }, 117 | "site_details": { 118 | "name": "", 119 | "address": { 120 | "address": "", 121 | "city": "", 122 | "state": "", 123 | "country": "", 124 | "zipcode": "" 125 | } 126 | } 127 | } 128 | ``` 129 | **Note** 130 | - 131 | - The `attributes` section for `group_details` supports all attributes that are available for `group_attributes` for [this API](https://developer.arubanetworks.com/aruba-central/reference/apigroupscreate_group_v3). 132 | 7. Once **central_token.json** & **workflow_variables.json** are updated with the relevant information, you can execute the script with the following command: 133 | ```bash 134 | python device_onboarding.py 135 | ``` 136 | **Note** 137 | - This script takes the following optional parameters to overide default filenames for the script 138 | - central_auth - Path of Central Token File 139 | - workflow_variables - Path of Workflows Variables File 140 | - You can run the following command to use the optional parameters - 141 | ```bash 142 | python device_onboarding.py --central_auth --workflow_variables 143 | ``` 144 | 8. If the script runs successfully, your terminal output should look like this - 145 |

146 | 147 |

148 | 149 | ## Central APIs used for this workflow - 150 | 1. [Add device using Mac and Serial number](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryadd_device) 151 | 2. [Assign subscription to a device](https://developer.arubanetworks.com/aruba-central/reference/acp_servicelicensewebviewsadmin_licenseapigw_assign_licenses-1) 152 | 3. [Create new group with specified properties](https://developer.arubanetworks.com/aruba-central/reference/apigroupscreate_group_v3) 153 | 4. [Create new template](https://developer.arubanetworks.com/aruba-central/reference/apitemplatescreate_template) 154 | 5. [Move devices to a group](https://developer.arubanetworks.com/aruba-central/reference/apigroupsmove_devices) 155 | 6. [Create Site](https://developer.arubanetworks.com/aruba-central/reference/sitesexternal_controllercreate_site) 156 | 7. [Associate Site to a list of devices](https://developer.arubanetworks.com/aruba-central/reference/sitesexternal_controllerassign_site_to_devices) 157 | -------------------------------------------------------------------------------- /device_onboarding/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /device_onboarding/device_templates/cx/template.txt: -------------------------------------------------------------------------------- 1 | ! 2 | !Version ArubaOS-CX ML.10.07.0010 3 | !export-password: default 4 | hostname Switch-3-1 5 | user admin group administrators password ciphertext AQBapbgm7oeLyFcCawq12yV/ShlA5EjWqgsTdCgcPufBz/HqYgAAAOz3cdjJcrCPsk1dqAJJthFqGgqsUj2rJq0SL0mCs4PiGpAcH5ELYwR8d/isNNXdTvjYZEdAxPRXMykBoqgjWkQI1f1r87BC9QFffrl+8tKkNwG5hIfUybPaveM42X8OLW/2 6 | clock timezone america/los_angeles 7 | ntp server 38.229.57.9 8 | ntp enable 9 | ! 10 | ! 11 | ! 12 | ! 13 | ! 14 | ! 15 | ssh server vrf default 16 | ssh server vrf mgmt 17 | vsf member 1 18 | type jl728a 19 | vlan 1,103 20 | spanning-tree 21 | interface mgmt 22 | no shutdown 23 | ip dhcp 24 | interface 1/1/1 25 | no shutdown 26 | vlan access 1 27 | interface 1/1/2 28 | no shutdown 29 | vlan access 103 30 | interface 1/1/3 31 | no shutdown 32 | vlan access 1 33 | interface 1/1/4 34 | no shutdown 35 | vlan access 1 36 | interface 1/1/5 37 | no shutdown 38 | vlan access 1 39 | interface 1/1/6 40 | no shutdown 41 | vlan access 1 42 | interface 1/1/7 43 | no shutdown 44 | vlan access 1 45 | interface 1/1/8 46 | no shutdown 47 | vlan access 1 48 | interface 1/1/9 49 | no shutdown 50 | vlan access 1 51 | interface 1/1/10 52 | no shutdown 53 | vlan access 1 54 | interface 1/1/11 55 | no shutdown 56 | vlan access 1 57 | interface 1/1/12 58 | no shutdown 59 | vlan access 1 60 | interface 1/1/13 61 | no shutdown 62 | vlan access 103 63 | interface 1/1/14 64 | no shutdown 65 | vlan access 103 66 | interface 1/1/15 67 | no shutdown 68 | vlan access 103 69 | interface 1/1/16 70 | no shutdown 71 | vlan access 1 72 | interface 1/1/17 73 | no shutdown 74 | vlan access 1 75 | interface 1/1/18 76 | no shutdown 77 | vlan access 1 78 | interface 1/1/19 79 | no shutdown 80 | vlan access 1 81 | interface 1/1/20 82 | no shutdown 83 | vlan access 1 84 | interface 1/1/21 85 | no shutdown 86 | vlan access 1 87 | interface 1/1/22 88 | no shutdown 89 | vlan access 1 90 | interface 1/1/23 91 | no shutdown 92 | vlan access 1 93 | interface 1/1/24 94 | no shutdown 95 | vlan access 1 96 | interface 1/1/25 97 | no shutdown 98 | vlan access 1 99 | interface 1/1/26 100 | no shutdown 101 | vlan access 1 102 | interface 1/1/27 103 | no shutdown 104 | vlan access 1 105 | interface 1/1/28 106 | no shutdown 107 | vlan access 1 108 | interface 1/1/29 109 | no shutdown 110 | vlan access 1 111 | interface 1/1/30 112 | no shutdown 113 | vlan access 1 114 | interface 1/1/31 115 | no shutdown 116 | vlan access 1 117 | interface 1/1/32 118 | no shutdown 119 | vlan access 1 120 | interface 1/1/33 121 | no shutdown 122 | vlan access 1 123 | interface 1/1/34 124 | no shutdown 125 | vlan access 1 126 | interface 1/1/35 127 | no shutdown 128 | vlan access 1 129 | interface 1/1/36 130 | no shutdown 131 | vlan access 1 132 | interface 1/1/37 133 | no shutdown 134 | vlan access 1 135 | interface 1/1/38 136 | no shutdown 137 | vlan access 1 138 | interface 1/1/39 139 | no shutdown 140 | vlan access 1 141 | interface 1/1/40 142 | no shutdown 143 | vlan access 1 144 | interface 1/1/41 145 | no shutdown 146 | vlan access 1 147 | interface 1/1/42 148 | no shutdown 149 | vlan access 1 150 | interface 1/1/43 151 | no shutdown 152 | vlan access 1 153 | interface 1/1/44 154 | no shutdown 155 | vlan access 1 156 | interface 1/1/45 157 | no shutdown 158 | vlan access 1 159 | interface 1/1/46 160 | no shutdown 161 | vlan access 1 162 | interface 1/1/47 163 | no shutdown 164 | vlan access 1 165 | interface 1/1/48 166 | no shutdown 167 | vlan access 1 168 | interface 1/1/49 169 | no shutdown 170 | vlan access 1 171 | interface 1/1/50 172 | no shutdown 173 | vlan access 1 174 | interface 1/1/51 175 | no shutdown 176 | vlan access 1 177 | interface 1/1/52 178 | no shutdown 179 | vlan access 1 180 | interface vlan 1 181 | ip address 192.168.0.115/24 182 | no ip dhcp 183 | interface vlan 103 184 | ip address 192.167.103.2/28 185 | ip route 0.0.0.0/0 192.168.0.1 186 | ip dns server-address 8.8.4.4 187 | ip dns server-address 8.8.8.8 188 | ! 189 | ! 190 | ! 191 | ! 192 | ! 193 | https-server vrf default 194 | https-server vrf mgmt 195 | configuration-lockout central managed -------------------------------------------------------------------------------- /device_onboarding/device_templates/iap/template.txt: -------------------------------------------------------------------------------- 1 | version 8.6.0.0-8.6.0 2 | virtual-controller-country US 3 | virtual-controller-key 11fac9b001e32b7bd122b96ecfe9fffce3a67f10111cc0ee94 4 | name SetMeUp-C2:18:CC 5 | terminal-access 6 | clock timezone none 00 00 7 | rf-band all 8 | report-rssi-to-central unassociated-and-associated-clients 9 | 10 | 11 | allowed-ap 7c:57:3c:c2:18:cc 12 | 13 | 14 | 15 | arm 16 | wide-bands 5ghz 17 | 80mhz-support 18 | min-tx-power 9 19 | max-tx-power 127 20 | band-steering-mode prefer-5ghz 21 | air-time-fairness-mode default-access 22 | channel-quality-aware-arm-disable 23 | client-aware 24 | scanning 25 | 26 | rf dot11g-radio-profile 27 | max-distance 0 28 | max-tx-power 9 29 | min-tx-power 6 30 | disable-arm-wids-functions off 31 | free-channel-index 40 32 | 33 | rf dot11a-radio-profile 34 | max-distance 0 35 | max-tx-power 18 36 | min-tx-power 12 37 | disable-arm-wids-functions off 38 | 39 | 40 | syslog-level warn ap-debug 41 | syslog-level warn network 42 | syslog-level warn security 43 | syslog-level warn system 44 | syslog-level warn user 45 | syslog-level warn user-debug 46 | syslog-level warn wireless 47 | 48 | 49 | 50 | extended-ssid 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | hash-mgmt-password 65 | hash-mgmt-user admin password hash 28908c8d02cca71001258beb0c3330db01bb017b4c11b053cb197112cb0de2cc9c80761d91 66 | 67 | 68 | 69 | wlan access-rule SetMeUp 70 | index 0 71 | rule masterip 0.0.0.0 match 6 80 80 permit 72 | rule masterip 0.0.0.0 match 6 4343 4343 permit 73 | rule any any match 17 67 68 permit 74 | rule any any match 17 53 53 permit 75 | 76 | wlan access-rule default_wired_port_profile 77 | index 1 78 | rule any any match any any any permit 79 | 80 | wlan access-rule wired-SetMeUp 81 | index 2 82 | rule masterip 0.0.0.0 match tcp 80 80 permit 83 | rule masterip 0.0.0.0 match tcp 4343 4343 permit 84 | rule any any match udp 67 68 permit 85 | rule any any match udp 53 53 permit 86 | 87 | wlan ssid-profile SetMeUp 88 | enable 89 | index 0 90 | type employee 91 | essid SetMeUp$APMAC3 92 | opmode opensystem 93 | max-authentication-failures 0 94 | vlan guest 95 | rf-band 2.4 96 | captive-portal disable 97 | dtim-period 1 98 | broadcast-filter none 99 | dmo-channel-utilization-threshold 90 100 | local-probe-req-thresh 0 101 | max-clients-threshold 64 102 | 103 | auth-survivability cache-time-out 24 104 | 105 | 106 | 107 | wlan captive-portal 108 | background-color 16777215 109 | banner-color 15329769 110 | banner-text "Welcome to Guest Network" 111 | terms-of-use "This network is not secure and use it at your own risk." 112 | use-policy "Please read and accept terms and conditions and then login." 113 | 114 | wlan external-captive-portal 115 | server localhost 116 | port 80 117 | url "/" 118 | auth-text "Authenticated" 119 | auto-whitelist-disable 120 | https 121 | 122 | 123 | blacklist-time 3600 124 | auth-failure-blacklist-time 3600 125 | 126 | 127 | ids 128 | wireless-containment none 129 | 130 | 131 | wired-port-profile wired-SetMeUp 132 | switchport-mode access 133 | allowed-vlan all 134 | native-vlan guest 135 | no shutdown 136 | access-rule-name wired-SetMeUp 137 | speed auto 138 | duplex auto 139 | no poe 140 | type guest 141 | captive-portal disable 142 | no dot1x 143 | 144 | wired-port-profile default_wired_port_profile 145 | switchport-mode trunk 146 | allowed-vlan all 147 | native-vlan 1 148 | no shutdown 149 | access-rule-name default_wired_port_profile 150 | speed auto 151 | duplex full 152 | no poe 153 | type employee 154 | captive-portal disable 155 | no dot1x 156 | 157 | 158 | enet0-port-profile default_wired_port_profile 159 | 160 | uplink 161 | preemption 162 | enforce none 163 | failover-internet-pkt-lost-cnt 10 164 | failover-internet-pkt-send-freq 30 165 | failover-vpn-timeout 180 166 | 167 | 168 | 169 | airgroup 170 | disable 171 | 172 | airgroupservice airplay 173 | disable 174 | description AirPlay 175 | 176 | airgroupservice airprint 177 | disable 178 | description AirPrint 179 | 180 | airgroupservice DIAL 181 | disable 182 | 183 | airgroupservice remotemgmt 184 | disable 185 | 186 | airgroupservice AmazonTV 187 | disable 188 | 189 | airgroupservice allowall 190 | disable 191 | 192 | airgroupservice googlecast 193 | disable 194 | 195 | airgroupservice itunes 196 | disable 197 | 198 | airgroupservice sharing 199 | disable 200 | 201 | airgroupservice chat 202 | disable 203 | 204 | airgroupservice "DLNA Print" 205 | disable 206 | 207 | airgroupservice "DLNA Media" 208 | disable 209 | 210 | 211 | 212 | 213 | 214 | clarity 215 | inline-sta-stats 216 | inline-auth-stats 217 | inline-dhcp-stats 218 | inline-dns-stats 219 | 220 | cluster-security 221 | allow-low-assurance-devices -------------------------------------------------------------------------------- /device_onboarding/media/script_terminal_output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/device_onboarding/media/script_terminal_output.gif -------------------------------------------------------------------------------- /device_onboarding/media/workflow_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/device_onboarding/media/workflow_overview.png -------------------------------------------------------------------------------- /device_onboarding/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | colored==2.2.3 5 | halo==0.0.31 6 | idna==3.7 7 | log-symbols==0.0.14 8 | pycentral==1.4.1 9 | PyYAML==6.0.1 10 | requests==2.32.0 11 | six==1.16.0 12 | spinners==0.0.24 13 | termcolor==2.3.0 14 | urllib3==2.2.2 15 | -------------------------------------------------------------------------------- /device_onboarding/workflow_variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "device_details": { 3 | "SWITCH": { 4 | "": { 5 | "mac_address": "", 6 | "central_subscription": "" 7 | }, 8 | "": { 9 | "mac_address": "", 10 | "central_subscription": "" 11 | } 12 | }, 13 | "IAP": { 14 | "": { 15 | "mac_address": "", 16 | "central_subscription": "" 17 | } 18 | } 19 | }, 20 | "group_details": { 21 | "name": "", 22 | "attributes": { 23 | "template_info": { 24 | "Wired": true, 25 | "Wireless": true 26 | }, 27 | "group_properties": { 28 | "AllowedDevTypes": [ 29 | "AccessPoints", 30 | "Switches" 31 | ], 32 | "Architecture": "Instant", 33 | "ApNetworkRole": "Standard", 34 | "AllowedSwitchTypes": [ 35 | "AOS_CX" 36 | ] 37 | } 38 | }, 39 | "config_templates": { 40 | "CX": { 41 | "template_name": "", 42 | "template_filename": "", 43 | "version": "", 44 | "model": "" 45 | }, 46 | "IAP": { 47 | "template_name": "", 48 | "template_filename": "", 49 | "version": "", 50 | "model": "" 51 | } 52 | } 53 | }, 54 | "site_details": { 55 | "name": "", 56 | "address": { 57 | "address": "", 58 | "city": "", 59 | "state": "", 60 | "country": "", 61 | "zipcode": "" 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /device_provisioning/README.md: -------------------------------------------------------------------------------- 1 | # Device Provisioning 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) library to achieve the following steps on an Aruba Central account- 3 | 1. Create a group (Template-based group) 4 | 2. Upload Configuration Template to Group 5 | 3. Move Devices to the newly created Group. 6 | 4. Create a Site 7 | 5. Move Devices to the newly created Site. 8 | 9 | ![Demo Workflow](media/workflow_overview.png) 10 | ## Prerequisite 11 | 1. All devices have valid Central licenses before the workflow is run 12 | 2. The group and site that the workflow creates does not already exist in the Central account. 13 | 3. Devices aren't associated with any existing sites on the Central account 14 | 15 | ## Installation Steps 16 | In order to run the script, please complete the steps below: 17 | 1. Clone this repository and `cd` into the workflow directory: 18 | ```bash 19 | git clone https://github.hpe.com/hpe/central-python-workflows 20 | cd central-python-workflows/device_provisioning 21 | ``` 22 | 23 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 24 | ```bash 25 | python -m venv env 26 | ``` 27 | 28 | 3. Activate the virtual environment 29 | In Mac/Linux: 30 | ```bash 31 | source env/bin/activate 32 | ``` 33 | In Windows: 34 | ```bash 35 | env/Scripts/activate.bat 36 | ``` 37 | 38 | 4. Install the packages required for the script 39 | ```bash 40 | python -m pip install -r requirements.txt 41 | ``` 42 | 43 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 44 | ```json 45 | { 46 | "central_info": { 47 | "base_url": "", 48 | "token": { 49 | "access_token": "" 50 | } 51 | }, 52 | "ssl_verify": true 53 | } 54 | ``` 55 | **Note** 56 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 57 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 58 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 59 | 60 | 6. Update the placeholder data of Group, Site & Device details in [workflow_variables.json](workflow_variables.json) to match your environment. 61 | ```json 62 | { 63 | "group_details": { 64 | "name": "", 65 | "attributes": { 66 | "template_info": { 67 | "Wired": true, 68 | "Wireless": true 69 | }, 70 | "group_properties": { 71 | "AllowedDevTypes": [ 72 | "AccessPoints", 73 | "Switches" 74 | ], 75 | "Architecture": "Instant", 76 | "ApNetworkRole": "Standard", 77 | "AllowedSwitchTypes": [ 78 | "AOS_CX" 79 | ] 80 | } 81 | }, 82 | "config_templates": { 83 | "CX": { 84 | "template_name": "", 85 | "template_filename": "", 86 | "version": "", 87 | "model": "" 88 | }, 89 | "IAP": { 90 | "template_name": "", 91 | "template_filename": "", 92 | "version": "", 93 | "model": "" 94 | } 95 | } 96 | }, 97 | "site_details": { 98 | "name": "", 99 | "address": { 100 | "address": "", 101 | "city": "", 102 | "state": "", 103 | "country": "", 104 | "zipcode": "" 105 | } 106 | }, 107 | "device_details": { 108 | "SWITCH": [ 109 | "", 110 | "" 111 | ], 112 | "IAP": [ 113 | "", 114 | "" 115 | ] 116 | } 117 | } 118 | ``` 119 | **Note** 120 | - The `attributes` section for `group_details` supports all attributes that are available for `group_attributes` for [this API](https://developer.arubanetworks.com/aruba-central/reference/apigroupscreate_group_v3). 121 | 122 | 7. Once **central_token.json** & **workflow_variables.json** are updated with the relevant information, you can execute the script with the following command: 123 | ```bash 124 | python device_provisioning.py 125 | ``` 126 | **Note** 127 | - This script takes the following optional parameters to overide default filenames for the script 128 | - central_auth - Path of Central Token File 129 | - workflow_variables - Path of Workflows Variables File 130 | - You can run the following command to use the optional parameters - 131 | ```bash 132 | python device_provisioning.py --central_auth --workflow_variables 133 | ``` 134 | 135 | 8. If the script runs successfully, your terminal output should look like this - 136 |

137 | 138 |

139 | 140 | ## Central APIs used for this workflow - 141 | 1. [Create new group with specified properties](https://developer.arubanetworks.com/aruba-central/reference/apigroupscreate_group_v3) 142 | 2. [Create new template](https://developer.arubanetworks.com/aruba-central/reference/apitemplatescreate_template) 143 | 3. [Move devices to a group](https://developer.arubanetworks.com/aruba-central/reference/apigroupsmove_devices) 144 | 4. [Create Site](https://developer.arubanetworks.com/aruba-central/reference/sitesexternal_controllercreate_site) 145 | 5. [Associate Site to a list of devices](https://developer.arubanetworks.com/aruba-central/reference/sitesexternal_controllerassign_site_to_devices) -------------------------------------------------------------------------------- /device_provisioning/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /device_provisioning/device_templates/cx/template.txt: -------------------------------------------------------------------------------- 1 | ! 2 | !Version ArubaOS-CX ML.10.07.0010 3 | !export-password: default 4 | hostname Switch-3-1 5 | user admin group administrators password ciphertext AQBapbgm7oeLyFcCawq12yV/ShlA5EjWqgsTdCgcPufBz/HqYgAAAOz3cdjJcrCPsk1dqAJJthFqGgqsUj2rJq0SL0mCs4PiGpAcH5ELYwR8d/isNNXdTvjYZEdAxPRXMykBoqgjWkQI1f1r87BC9QFffrl+8tKkNwG5hIfUybPaveM42X8OLW/2 6 | clock timezone america/los_angeles 7 | ntp server 38.229.57.9 8 | ntp enable 9 | ! 10 | ! 11 | ! 12 | ! 13 | ! 14 | ! 15 | ssh server vrf default 16 | ssh server vrf mgmt 17 | vsf member 1 18 | type jl728a 19 | vlan 1,103 20 | spanning-tree 21 | interface mgmt 22 | no shutdown 23 | ip dhcp 24 | interface 1/1/1 25 | no shutdown 26 | vlan access 1 27 | interface 1/1/2 28 | no shutdown 29 | vlan access 103 30 | interface 1/1/3 31 | no shutdown 32 | vlan access 1 33 | interface 1/1/4 34 | no shutdown 35 | vlan access 1 36 | interface 1/1/5 37 | no shutdown 38 | vlan access 1 39 | interface 1/1/6 40 | no shutdown 41 | vlan access 1 42 | interface 1/1/7 43 | no shutdown 44 | vlan access 1 45 | interface 1/1/8 46 | no shutdown 47 | vlan access 1 48 | interface 1/1/9 49 | no shutdown 50 | vlan access 1 51 | interface 1/1/10 52 | no shutdown 53 | vlan access 1 54 | interface 1/1/11 55 | no shutdown 56 | vlan access 1 57 | interface 1/1/12 58 | no shutdown 59 | vlan access 1 60 | interface 1/1/13 61 | no shutdown 62 | vlan access 103 63 | interface 1/1/14 64 | no shutdown 65 | vlan access 103 66 | interface 1/1/15 67 | no shutdown 68 | vlan access 103 69 | interface 1/1/16 70 | no shutdown 71 | vlan access 1 72 | interface 1/1/17 73 | no shutdown 74 | vlan access 1 75 | interface 1/1/18 76 | no shutdown 77 | vlan access 1 78 | interface 1/1/19 79 | no shutdown 80 | vlan access 1 81 | interface 1/1/20 82 | no shutdown 83 | vlan access 1 84 | interface 1/1/21 85 | no shutdown 86 | vlan access 1 87 | interface 1/1/22 88 | no shutdown 89 | vlan access 1 90 | interface 1/1/23 91 | no shutdown 92 | vlan access 1 93 | interface 1/1/24 94 | no shutdown 95 | vlan access 1 96 | interface 1/1/25 97 | no shutdown 98 | vlan access 1 99 | interface 1/1/26 100 | no shutdown 101 | vlan access 1 102 | interface 1/1/27 103 | no shutdown 104 | vlan access 1 105 | interface 1/1/28 106 | no shutdown 107 | vlan access 1 108 | interface 1/1/29 109 | no shutdown 110 | vlan access 1 111 | interface 1/1/30 112 | no shutdown 113 | vlan access 1 114 | interface 1/1/31 115 | no shutdown 116 | vlan access 1 117 | interface 1/1/32 118 | no shutdown 119 | vlan access 1 120 | interface 1/1/33 121 | no shutdown 122 | vlan access 1 123 | interface 1/1/34 124 | no shutdown 125 | vlan access 1 126 | interface 1/1/35 127 | no shutdown 128 | vlan access 1 129 | interface 1/1/36 130 | no shutdown 131 | vlan access 1 132 | interface 1/1/37 133 | no shutdown 134 | vlan access 1 135 | interface 1/1/38 136 | no shutdown 137 | vlan access 1 138 | interface 1/1/39 139 | no shutdown 140 | vlan access 1 141 | interface 1/1/40 142 | no shutdown 143 | vlan access 1 144 | interface 1/1/41 145 | no shutdown 146 | vlan access 1 147 | interface 1/1/42 148 | no shutdown 149 | vlan access 1 150 | interface 1/1/43 151 | no shutdown 152 | vlan access 1 153 | interface 1/1/44 154 | no shutdown 155 | vlan access 1 156 | interface 1/1/45 157 | no shutdown 158 | vlan access 1 159 | interface 1/1/46 160 | no shutdown 161 | vlan access 1 162 | interface 1/1/47 163 | no shutdown 164 | vlan access 1 165 | interface 1/1/48 166 | no shutdown 167 | vlan access 1 168 | interface 1/1/49 169 | no shutdown 170 | vlan access 1 171 | interface 1/1/50 172 | no shutdown 173 | vlan access 1 174 | interface 1/1/51 175 | no shutdown 176 | vlan access 1 177 | interface 1/1/52 178 | no shutdown 179 | vlan access 1 180 | interface vlan 1 181 | ip address 192.168.0.115/24 182 | no ip dhcp 183 | interface vlan 103 184 | ip address 192.167.103.2/28 185 | ip route 0.0.0.0/0 192.168.0.1 186 | ip dns server-address 8.8.4.4 187 | ip dns server-address 8.8.8.8 188 | ! 189 | ! 190 | ! 191 | ! 192 | ! 193 | https-server vrf default 194 | https-server vrf mgmt 195 | configuration-lockout central managed -------------------------------------------------------------------------------- /device_provisioning/device_templates/iap/template.txt: -------------------------------------------------------------------------------- 1 | version 8.6.0.0-8.6.0 2 | virtual-controller-country US 3 | virtual-controller-key 11fac9b001e32b7bd122b96ecfe9fffce3a67f10111cc0ee94 4 | name SetMeUp-C2:18:CC 5 | terminal-access 6 | clock timezone none 00 00 7 | rf-band all 8 | report-rssi-to-central unassociated-and-associated-clients 9 | 10 | 11 | allowed-ap 7c:57:3c:c2:18:cc 12 | 13 | 14 | 15 | arm 16 | wide-bands 5ghz 17 | 80mhz-support 18 | min-tx-power 9 19 | max-tx-power 127 20 | band-steering-mode prefer-5ghz 21 | air-time-fairness-mode default-access 22 | channel-quality-aware-arm-disable 23 | client-aware 24 | scanning 25 | 26 | rf dot11g-radio-profile 27 | max-distance 0 28 | max-tx-power 9 29 | min-tx-power 6 30 | disable-arm-wids-functions off 31 | free-channel-index 40 32 | 33 | rf dot11a-radio-profile 34 | max-distance 0 35 | max-tx-power 18 36 | min-tx-power 12 37 | disable-arm-wids-functions off 38 | 39 | 40 | syslog-level warn ap-debug 41 | syslog-level warn network 42 | syslog-level warn security 43 | syslog-level warn system 44 | syslog-level warn user 45 | syslog-level warn user-debug 46 | syslog-level warn wireless 47 | 48 | 49 | 50 | extended-ssid 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | hash-mgmt-password 65 | hash-mgmt-user admin password hash 28908c8d02cca71001258beb0c3330db01bb017b4c11b053cb197112cb0de2cc9c80761d91 66 | 67 | 68 | 69 | wlan access-rule SetMeUp 70 | index 0 71 | rule masterip 0.0.0.0 match 6 80 80 permit 72 | rule masterip 0.0.0.0 match 6 4343 4343 permit 73 | rule any any match 17 67 68 permit 74 | rule any any match 17 53 53 permit 75 | 76 | wlan access-rule default_wired_port_profile 77 | index 1 78 | rule any any match any any any permit 79 | 80 | wlan access-rule wired-SetMeUp 81 | index 2 82 | rule masterip 0.0.0.0 match tcp 80 80 permit 83 | rule masterip 0.0.0.0 match tcp 4343 4343 permit 84 | rule any any match udp 67 68 permit 85 | rule any any match udp 53 53 permit 86 | 87 | wlan ssid-profile SetMeUp 88 | enable 89 | index 0 90 | type employee 91 | essid SetMeUp$APMAC3 92 | opmode opensystem 93 | max-authentication-failures 0 94 | vlan guest 95 | rf-band 2.4 96 | captive-portal disable 97 | dtim-period 1 98 | broadcast-filter none 99 | dmo-channel-utilization-threshold 90 100 | local-probe-req-thresh 0 101 | max-clients-threshold 64 102 | 103 | auth-survivability cache-time-out 24 104 | 105 | 106 | 107 | wlan captive-portal 108 | background-color 16777215 109 | banner-color 15329769 110 | banner-text "Welcome to Guest Network" 111 | terms-of-use "This network is not secure and use it at your own risk." 112 | use-policy "Please read and accept terms and conditions and then login." 113 | 114 | wlan external-captive-portal 115 | server localhost 116 | port 80 117 | url "/" 118 | auth-text "Authenticated" 119 | auto-whitelist-disable 120 | https 121 | 122 | 123 | blacklist-time 3600 124 | auth-failure-blacklist-time 3600 125 | 126 | 127 | ids 128 | wireless-containment none 129 | 130 | 131 | wired-port-profile wired-SetMeUp 132 | switchport-mode access 133 | allowed-vlan all 134 | native-vlan guest 135 | no shutdown 136 | access-rule-name wired-SetMeUp 137 | speed auto 138 | duplex auto 139 | no poe 140 | type guest 141 | captive-portal disable 142 | no dot1x 143 | 144 | wired-port-profile default_wired_port_profile 145 | switchport-mode trunk 146 | allowed-vlan all 147 | native-vlan 1 148 | no shutdown 149 | access-rule-name default_wired_port_profile 150 | speed auto 151 | duplex full 152 | no poe 153 | type employee 154 | captive-portal disable 155 | no dot1x 156 | 157 | 158 | enet0-port-profile default_wired_port_profile 159 | 160 | uplink 161 | preemption 162 | enforce none 163 | failover-internet-pkt-lost-cnt 10 164 | failover-internet-pkt-send-freq 30 165 | failover-vpn-timeout 180 166 | 167 | 168 | 169 | airgroup 170 | disable 171 | 172 | airgroupservice airplay 173 | disable 174 | description AirPlay 175 | 176 | airgroupservice airprint 177 | disable 178 | description AirPrint 179 | 180 | airgroupservice DIAL 181 | disable 182 | 183 | airgroupservice remotemgmt 184 | disable 185 | 186 | airgroupservice AmazonTV 187 | disable 188 | 189 | airgroupservice allowall 190 | disable 191 | 192 | airgroupservice googlecast 193 | disable 194 | 195 | airgroupservice itunes 196 | disable 197 | 198 | airgroupservice sharing 199 | disable 200 | 201 | airgroupservice chat 202 | disable 203 | 204 | airgroupservice "DLNA Print" 205 | disable 206 | 207 | airgroupservice "DLNA Media" 208 | disable 209 | 210 | 211 | 212 | 213 | 214 | clarity 215 | inline-sta-stats 216 | inline-auth-stats 217 | inline-dhcp-stats 218 | inline-dns-stats 219 | 220 | cluster-security 221 | allow-low-assurance-devices -------------------------------------------------------------------------------- /device_provisioning/media/script_terminal_output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/device_provisioning/media/script_terminal_output.gif -------------------------------------------------------------------------------- /device_provisioning/media/workflow_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/device_provisioning/media/workflow_overview.png -------------------------------------------------------------------------------- /device_provisioning/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | halo==0.0.31 5 | idna==3.7 6 | pycentral==1.4.1 7 | PyYAML==6.0.1 8 | requests==2.32.2 9 | six==1.16.0 10 | spinners==0.0.24 11 | termcolor==2.3.0 12 | urllib3==2.2.2 -------------------------------------------------------------------------------- /device_provisioning/workflow_variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "group_details": { 3 | "name": "", 4 | "attributes": { 5 | "template_info": { 6 | "Wired": true, 7 | "Wireless": true 8 | }, 9 | "group_properties": { 10 | "AllowedDevTypes": [ 11 | "AccessPoints", 12 | "Switches" 13 | ], 14 | "Architecture": "Instant", 15 | "ApNetworkRole": "Standard", 16 | "AllowedSwitchTypes": [ 17 | "AOS_CX" 18 | ] 19 | } 20 | }, 21 | "config_templates": { 22 | "CX": { 23 | "template_name": "", 24 | "template_filename": "", 25 | "version": "", 26 | "model": "" 27 | }, 28 | "IAP": { 29 | "template_name": "", 30 | "template_filename": "", 31 | "version": "", 32 | "model": "" 33 | } 34 | } 35 | }, 36 | "site_details": { 37 | "name": "", 38 | "address": { 39 | "address": "", 40 | "city": "", 41 | "state": "", 42 | "country": "", 43 | "zipcode": "" 44 | } 45 | }, 46 | "device_details": { 47 | "SWITCH": [ 48 | "", 49 | "" 50 | ], 51 | "IAP": [ 52 | "", 53 | "" 54 | ] 55 | } 56 | } -------------------------------------------------------------------------------- /inventory_to_excel/README.md: -------------------------------------------------------------------------------- 1 | # Inventory to Excel Workflows 2 | 3 | This README presupposes general knowledge of how to use ArubaCentral API's and execute workflow scripts. Please see [here](https://github.com/aruba/pycentral/blob/master/README.md) 4 | for detailed information on installing pycentral and getting setup to execute workflow scripts. 5 | 6 | Inventory to excel workflows are used to create excel files populated with device details from devices currently in inventory. 7 | 8 | ### Workflow Functionality 9 | 10 | 1. This workflow should be used to collect all device details from devices in an account's inventory and export this data to an excel workbook. 11 | 12 | 2. Device details included are: Aruba Part Number, Customer ID, Customer Name, Device Type, IMEI, Mac Address, Model, Serial, Services, Subscription Key, and Tier type. 13 | 14 | 3. Device types received from inventory can be filtered using the sku_type CLI argument described in section 2 of [executing the workflow](#executing-the-workflow). 15 | 16 | 4. Additonal CLI options are available including: config filepath, excel filename, limit, offset. 17 | 18 | ### How To Install 19 | In order to run the workflow script please install the requirements which includes Pycentral. Please refer to the link 20 | above for more information on installing Pycentral. 21 | 1. Clone the repository. 22 | ``` 23 | git clone https://github.com/aruba/central-python-workflows.git 24 | cd inventory_to_excel 25 | ``` 26 | 27 | 2. install requirements.txt. Make sure python version 3 is installed in system. 28 | ``` 29 | $ pip install -r .\requirements.txt 30 | ``` 31 | 32 | ### Other Setup 33 | A config file containing credential information for your Aruba Central account is required to run this workflow. The details and structure 34 | for how to create this can be found [here](https://github.com/aruba/pycentral/tree/master/sample_scripts). The config filename should be passed as a CLI argument during execution. 35 | ```python 36 | --central_auth <"path to config file"> 37 | ``` 38 | 39 | Now you can start executing the script. 40 | 41 | ### Executing The Workflow 42 | 1. The workflow can be ran as is with a config file named central_token.yaml in the working directory. 43 | 44 | ``` 45 | $ python inventory_excel_workflow.py 46 | ``` 47 | 48 | This will create a new .xlsx document named inventory.xlsx in the working directory. 49 | The .xlsx file will contain the details for all devices in inventory as documented in the [API](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryget_devices). 50 | 51 | 52 | 2. Providing input variables to the workflow is optional. One or multiple of the following options can be used through CLI arguments. 53 | * Flags 54 | 55 | Output format: 56 | By default the workflow outputs an excel file in the .xlsx filetype. Output format can be changed optionally with the -c flag to output as .csv instead. If the -c flag is set the workflow will output the new file as a .csv. 57 | ``` 58 | $ python inventory_excel_workflow.py -c 59 | ``` 60 | 61 | * Provide variables to script upon execution 62 | 63 | central_auth: 64 | Sets the file path to central credential file. 65 | ``` 66 | $ python inventory_excel_workflow.py --central_auth 67 | ``` 68 | 69 | filename: 70 | Sets the name of the output file. 71 | ``` 72 | $ python inventory_excel_workflow.py --filename 73 | ``` 74 | 75 | sku_type parameters: 76 | Sets the specific device type to pull device details for. Only one option at a time is currently supported. 77 | Valid inputs: all, iap, switch, controller, gateway, **vgw, cap, boc, all_ap, all_controller, others. 78 | ``` 79 | $ python inventory_excel_workflow.py --sku_type 80 | ``` 81 | 82 | limit and offset parameters: 83 | Sets pagination for API calls. Should be used together. 84 | ``` 85 | $ python inventory_excel_workflow.py --limit --offset 86 | ``` 87 | 88 | **See Known Bugs section 89 | 90 | ## Documentation: 91 | * **Python package documentation:** [pycentral module documentation](https://pycentral.readthedocs.io/en/latest/) 92 | * **Use-Cases and Workflows:** [Aruba Developer Hub](https://developer.arubanetworks.com/aruba-central) 93 | * **API Reference:** [New Device Inventory](https://developer.arubanetworks.com/aruba-central/reference/acp_servicenb_apiapidevice_inventoryget_devices) 94 | 95 | ## Troubleshooting Issues 96 | If you encounter module import errors, make sure that the package has been installed correctly. 97 | 98 | ## Known Bugs 99 | 1. sku_type 'vgw' currently does not work. It should exit with a bad request error and a response code of 500. 100 | -------------------------------------------------------------------------------- /inventory_to_excel/inventory.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from pycentral.new_device_inventory import Inventory 24 | import xlsxwriter 25 | import csv as c 26 | import sys 27 | 28 | 29 | class InventoryToExcel(object): 30 | """ 31 | Contains functions to create excel files from device inventory data. 32 | """ 33 | 34 | def devices_to_excel(self, conn, sku_type='all', csv=False, 35 | filename="inventory", limit=0, offset=0): 36 | """Create excel document with target sku_type devices from inventory. 37 | Excel document is created in working directory. 38 | 39 | :param conn: Instance of class:`pycentral.ArubaCentralBase`. 40 | :type conn: class:`pycentral.ArubaCentralBase` 41 | :param sku_type: target device sku type to pull from inventory. 42 | Acceptable arguments: all, iap, switch, controller, gateway, 43 | vgw, cap, boc, all_ap, all_controller, others. 44 | :type sku_type: str 45 | :param csv: Flag to change output to csv. 46 | :type csv: bool 47 | :param filename: filename for created document. 48 | :type filename: str, optional 49 | :param limit: Pagination limit. Defaults to 0, which is intrepreted as 50 | get all. Maximum limit per request is 50. 51 | :type limit: int, optional 52 | :param offset: Pagination offset, defaults to 0. 53 | :type offset: int, optional 54 | """ 55 | 56 | # Call API 57 | get_resp = Inventory.get_inventory( 58 | self, conn, sku_type, limit=limit, offset=offset) 59 | if get_resp["code"] != 200: 60 | sys.exit( 61 | "Bad request for get_inventory() response code: %d. " 62 | "Check parameters. Exiting..." % get_resp["code"]) 63 | 64 | # Assign data from response. 65 | device_list = get_resp["msg"]["devices"] 66 | device_total = get_resp["msg"]["total"] 67 | if len(device_list) != 0: 68 | col_keys = list(device_list[0].keys()) 69 | else: 70 | sys.exit("No devices found matching specifications. Exiting...") 71 | 72 | # Handle total devices greater than max limit. 73 | if limit == 0: 74 | while len(device_list) < device_total: 75 | # Increment pagination offset. 76 | offset += 50 77 | # Get next set of devices. 78 | get_resp = Inventory.get_inventory( 79 | self, conn, sku_type, limit=limit, offset=offset) 80 | if get_resp["code"] != 200: 81 | sys.exit( 82 | "Bad request for get_inventory() response code: %d. " 83 | "Check parameters. Exiting..." % get_resp["code"]) 84 | 85 | # Add new set of devices to device_list. 86 | device_list.append(get_resp["msg"]["devices"]) 87 | 88 | # Setup doc headers and filetype. 89 | col_headers = ["Aruba Part Number", "Customer ID", "Customer Name", 90 | "Device Type", "IMEI", "Mac Address", "Model", 91 | "Serial", "Services", "Subscription Key", "Tier Type"] 92 | filename = (filename + '.csv') if csv else (filename + '.xlsx') 93 | 94 | if not csv: 95 | # Create excel file, worksheet, and formatting. 96 | workbook = xlsxwriter.Workbook(filename) 97 | worksheet = workbook.add_worksheet() 98 | bold = workbook.add_format({'bold': True}) 99 | 100 | # Setup headers and coordinates. 101 | for i in range(len(col_headers)): 102 | worksheet.write(0, i, col_headers[i], bold) 103 | row, col = 1, 0 104 | 105 | # Write device info to cells. 106 | for device in device_list: 107 | for key in col_keys: 108 | # Switch to proper format for writing. 109 | match device[key]: 110 | case str(): 111 | worksheet.write(row, col, device[key]) 112 | case list(): 113 | data = ', '.join(device[key]) 114 | worksheet.write(row, col, data) 115 | case _: 116 | worksheet.write(row, col, 'null') 117 | col += 1 118 | 119 | row += 1 120 | col = 0 121 | 122 | worksheet.autofit() 123 | workbook.close() 124 | else: 125 | # Open csv file and setup writer. 126 | with open(filename, 'w', newline='') as csvfile: 127 | writer = c.DictWriter(csvfile, fieldnames=col_keys) 128 | 129 | # Write to csv. 130 | writer.writeheader() 131 | for device in device_list: 132 | writer.writerow(device) 133 | -------------------------------------------------------------------------------- /inventory_to_excel/inventory_excel_workflow.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | 5 | """ 6 | In this sample, we show how to use the inventory_excel_workflow. This 7 | includes creation of an ArubaCentralBase instance through the usage of a 8 | config file, which is required for pycentral API usage. The primary function 9 | of this workflow is creating a new excel file populated with device data from 10 | device inventory. By default this workflow will pull data from all devices in 11 | inventory. Device type data can be further filtered by specifiying sku_type, 12 | limit, and offset in the CLI as arguments. Full workflow documentation can be 13 | found in the README. 14 | """ 15 | 16 | from pycentral.workflows.workflows_utils import get_conn_from_file 17 | from inventory import InventoryToExcel 18 | from argparse import ArgumentParser 19 | import sys 20 | 21 | 22 | def main(): 23 | args = define_arguments() 24 | 25 | # Create ArubaCentralBase Instance. 26 | central = get_conn_from_file(filename=args.central_auth) 27 | 28 | inventory_workflow = InventoryToExcel() 29 | # Call function to create output doc with CLI arguments. 30 | inventory_workflow.devices_to_excel(conn=central, sku_type=args.sku_type, 31 | filename=args.filename, 32 | limit=args.limit, 33 | offset=args.offset, 34 | csv=args.c) 35 | 36 | 37 | def define_arguments(): 38 | """ 39 | This function defines commmand line arguments that can be used with this 40 | workflow. 41 | 42 | return: Argparse namespace with device type, limit, and offset filters. 43 | type return: argparse.Namespace 44 | """ 45 | 46 | description = "This workflow gets device details from an "\ 47 | "Aruba Central accounts inventory and exports details"\ 48 | " to an excel file." 49 | sku_help = "Device type filter. Valid options are: "\ 50 | "all, iap, switch, controller, gateway, vgw, cap, boc, all_ap,\ 51 | all_controller, others." 52 | 53 | # Add argument definitions to parser. 54 | parser = ArgumentParser(description=description) 55 | parser.add_argument('-c', help=('Output as csv'), action='store_true') 56 | parser.add_argument('--central_auth', help=('Central credential auth' 57 | ' filepath'), 58 | default='central_token.yaml') 59 | parser.add_argument('--sku_type', help=(sku_help), type=validate_sku, 60 | default='all') 61 | parser.add_argument('--filename', help=('Output filename.'), 62 | default='inventory') 63 | parser.add_argument('--limit', help=('Pagination limit for API. Should be' 64 | ' used with offset.'), default=0) 65 | parser.add_argument('--offset', help=('Pagination offest for API. Should' 66 | ' be used with limit.'), default=0) 67 | 68 | return parser.parse_args() 69 | 70 | 71 | def validate_sku(sku_type): 72 | """ 73 | Validates input for sku_type CLI argument. 74 | 75 | :param string: sku_type string 76 | """ 77 | 78 | valid_sku = ['all', 'iap', 'switch', 'controller', 'gateway', 'vgw', 'cap', 79 | 'boc', 'all_ap', 'all_controller', 'others'] 80 | 81 | if sku_type.lower() not in valid_sku: 82 | sys.exit("Invalid argument: '%s' for sku_type. Exiting..." % sku_type) 83 | 84 | return sku_type 85 | 86 | 87 | if __name__ == "__main__": 88 | main() 89 | -------------------------------------------------------------------------------- /inventory_to_excel/requirements.txt: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/inventory_to_excel/requirements.txt -------------------------------------------------------------------------------- /msp_customer_deletion/README.md: -------------------------------------------------------------------------------- 1 | # MSP Customer Deletion 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) library to automate the following steps on an Aruba Central account with [MSP mode](https://www.arubanetworks.com/techdocs/central/latest/content/nms/msp/overview.htm)- 3 | 1. Unassigns all devices & licenses within the customer's Aruba Central Instance. The devices & licenses will be moved back to the MSP's inventory. 4 | 2. Uninstall the customer's Aruba Central instance 5 | 3. Delete the customer's Greenlake Instance 6 | 7 | ![Demo Workflow](media/workflow_overview.png) 8 | ## Installation Steps 9 | In order to run the script, please complete the steps below: 10 | 1. Clone this repository and `cd` into the workflow directory: 11 | ```bash 12 | git clone https://github.hpe.com/hpe/central-python-workflows 13 | cd central-python-workflows/msp_customer_deletion 14 | ``` 15 | 16 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 17 | ```bash 18 | python -m venv env 19 | ``` 20 | 21 | 3. Activate the virtual environment 22 | In Mac/Linux: 23 | ```bash 24 | source env/bin/activate 25 | ``` 26 | In Windows: 27 | ```bash 28 | env/Scripts/activate.bat 29 | ``` 30 | 4. Install the packages required for the script 31 | ```bash 32 | python -m pip install -r requirements.txt 33 | ``` 34 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 35 | ```json 36 | { 37 | "central_info": { 38 | "base_url": "", 39 | "token": { 40 | "access_token": "" 41 | } 42 | }, 43 | "ssl_verify": true 44 | } 45 | ``` 46 | **Note** 47 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 48 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 49 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 50 | 6. Fill up the [workflow_variables.json](workflow_variables.json) file with the name or id of the customer(s) you would like to delete from the MSP account. 51 | 7. Once **central_token.json** & **workflow_variables.json** are updated with the relevant information, you can execute the script with the following command: 52 | ```bash 53 | python msp_customer_deletion.py 54 | ``` 55 | **Note** 56 | - This script takes the following optional parameters to overide default filenames for the script 57 | - central_auth - Path of Central Token File 58 | - workflow_variables - Path of Workflows Variables File 59 | - ou can run the following command to use the optional parameters - 60 | ```bash 61 | python msp_customer_onboarding.py --central_auth --workflow_variables 62 | 8. If the script runs successfully, your terminal output should look like this - 63 |

64 | 65 |

66 | 67 | ## Central APIs used for this workflow - 68 | 1. [Get list of customers under the MSP account](https://developer.arubanetworks.com/aruba-central/reference/apiviewsmsp_apiget_customers) 69 | 2. [Un-assign all devices from Tenant/end-customer](https://developer.arubanetworks.com/aruba-central/reference/apiviewsmsp_apiunassign_tenant_devices) 70 | 3. [Delete a customer](https://developer.arubanetworks.com/aruba-central/reference/apiviewsmsp_apidelete_customer) -------------------------------------------------------------------------------- /msp_customer_deletion/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /msp_customer_deletion/media/script_terminal_output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/msp_customer_deletion/media/script_terminal_output.gif -------------------------------------------------------------------------------- /msp_customer_deletion/media/workflow_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/msp_customer_deletion/media/workflow_overview.png -------------------------------------------------------------------------------- /msp_customer_deletion/msp_customer_deletion.py: -------------------------------------------------------------------------------- 1 | from termcolor import colored 2 | from pycentral.workflows.workflows_utils import get_conn_from_file 3 | from argparse import ArgumentParser 4 | from pycentral.msp import MSP 5 | from halo import Halo 6 | import json 7 | import sys 8 | 9 | m = MSP() 10 | 11 | 12 | def main(): 13 | # Define Command-line Arguments 14 | args = define_arguments() 15 | 16 | # Get instance of ArubaCentralBase from the central_filename 17 | global central_conn 18 | central_conn = get_conn_from_file(filename=args.central_auth) 19 | 20 | # Load in Workflow Variables 21 | customer_list = json.loads(open(args.customer_list, "r").read()) 22 | # Fetch attributes of customer(s) that need to be deleted 23 | delete_customer_data = get_selected_customer_data(customer_list) 24 | # Get user confirmation before deleting the customer(s) 25 | user_confirmation(delete_customer_data) 26 | # Unassign all licenses & devices in the customer account and then delete the customer 27 | updated_delete_customer_data = list(map(add_delete_status, delete_customer_data)) 28 | # Output result of deletion operation for customer(s) 29 | output_result(updated_delete_customer_data) 30 | 31 | 32 | def define_arguments(): 33 | """This function defines the command line arguments that can be used with this PyCentral script 34 | 35 | Returns: 36 | argparse.Namespace: Returns argparse namespace with central authorization & workflow variables file names 37 | """ 38 | 39 | description = 'This script unassigns devices & subscriptions from the provided customers\' Aruba Central Instance, and then deletes the customers\'s Greenlake account.' 40 | 41 | parser = ArgumentParser(description=description) 42 | parser.add_argument( 43 | '--central_auth', help=('Central API Authorization file path'), default='central_token.json') 44 | parser.add_argument( 45 | '--customer_list', help=('Customer List file path'), default='workflow_variables.json') 46 | return parser.parse_args() 47 | 48 | @Halo(text='Fetching data of customers that will be deleted...', spinner='simpleDots') 49 | def get_selected_customer_data(customer_list): 50 | all_customers = m.get_all_customers(central_conn) 51 | customer_data = [] 52 | if (type(all_customers) is not list): 53 | exit('Unable to fetch customer list') 54 | valid_input_file_keys = ['customer_ids', 'customer_names'] 55 | for key in valid_input_file_keys: 56 | attribute = key[:-1] 57 | if key in customer_list and len(customer_list[key]) > 0: 58 | for customer_attribute in customer_list[key]: 59 | found_customer = next((customer for customer in all_customers if customer[attribute] == customer_attribute), None) 60 | if found_customer: 61 | if found_customer['customer_name'] not in [customer['name'] for customer in customer_data]: 62 | customer_data.append({ 63 | 'name': found_customer['customer_name'], 64 | 'id': found_customer['customer_id'] 65 | }) 66 | continue 67 | else: 68 | sys.exit(f"Unable to find customer with ID {colored(customer_attribute, 'red')} in MSP account. Please provide a valid customer ID.") 69 | 70 | if len(customer_data) == 0: 71 | sys.exit(colored( 72 | "Customer list is empty. Please provide either the ID or the name of the customer you would like to delete.", 'red')) 73 | return customer_data 74 | 75 | 76 | 77 | def user_confirmation(delete_customer_data): 78 | num_customers = len(delete_customer_data) 79 | customer_name_list = ", ".join([customer["name"] for customer in delete_customer_data]) 80 | confirmationText = f"""The script will be executed for {colored(num_customers, 'blue')} customers({colored(customer_name_list, 'blue')}) in the MSP account 81 | Continuing this script will do the following to the above mentioned customer account(s) - 82 | 1. All users will lose access to the customer account 83 | 2. It will permanently delete all device and user data in the customer account. 84 | 3. All devices & subscriptions will be moved to the MSP's inventory. 85 | 4. The customer's Central & Greenlake Instance will be deleted 86 | 5. The deletion is irreversable and cannot be canceled or undone once the process has begun 87 | """ 88 | print(confirmationText) 89 | userInput = input( 90 | colored("Would you like to proceed with the script (y/n)? ", "yellow")) 91 | if userInput.lower() == "y": 92 | print(colored("Continuing...", "blue")) 93 | else: 94 | sys.exit(colored("Exiting script..", "red")) 95 | 96 | 97 | def add_delete_status(customer_data): 98 | customer_data['delete_status'] = delete_customer(customer_data['id']) 99 | return customer_data 100 | 101 | def delete_customer(customer_id): 102 | unassign_step = unassign_customer_devices(customer_id) 103 | if unassign_step: 104 | delete_step = delete_customer_instance(customer_id) 105 | if delete_step: 106 | return True 107 | return False 108 | 109 | 110 | @Halo(text='Unassigning devices & licenses from customer\'s Central instance...', spinner='simpleDots') 111 | def unassign_customer_devices(customer_id): 112 | resp = m.unassign_all_customer_device( 113 | central_conn, customer_id=customer_id) 114 | if resp['code'] != 200: 115 | print( 116 | colored(f'Unable to unassign all devices from customer with ID - {customer_id}', 'red')) 117 | return False 118 | return True 119 | 120 | 121 | @Halo(text='Deleting customer\'s Central instance & Greenlake account...', spinner='simpleDots') 122 | def delete_customer_instance(customer_id): 123 | resp = m.delete_customer( 124 | central_conn, customer_id=customer_id) 125 | if resp['code'] != 200: 126 | print( 127 | colored(f'Unable to delete customer with ID - {customer_id}', 'red')) 128 | return False 129 | return True 130 | 131 | 132 | def output_result(delete_customer_data): 133 | successful_customers = [customer for customer in delete_customer_data if customer['delete_status']] 134 | error_customers = [customer for customer in delete_customer_data if not customer['delete_status']] 135 | 136 | if len(successful_customers) > 0: 137 | formatted_customer_string = list(map(format_customer_name_id, successful_customers)) 138 | print( 139 | f'Successfully deleted {len(successful_customers)} customer(s) with ID - {colored(", ".join(formatted_customer_string), "green")}') 140 | if len(error_customers) > 0: 141 | formatted_customer_string = list(map(format_customer_name_id, error_customers)) 142 | print( 143 | f'Error deleting {len(error_customers)} customer(s) with ID - {colored(", ".join(formatted_customer_string), "red")}') 144 | 145 | def format_customer_name_id(customer): 146 | return f"{customer['name']} ({customer['id']})" 147 | 148 | if __name__ == "__main__": 149 | main() 150 | -------------------------------------------------------------------------------- /msp_customer_deletion/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | halo==0.0.31 5 | idna==3.7 6 | log-symbols==0.0.14 7 | pycentral==1.4.1 8 | PyYAML==6.0.1 9 | requests==2.31.0 10 | six==1.16.0 11 | spinners==0.0.24 12 | termcolor==2.4.0 13 | urllib3==2.2.2 14 | -------------------------------------------------------------------------------- /msp_customer_deletion/workflow_variables.json: -------------------------------------------------------------------------------- 1 | { 2 | "customer_ids": ["", ""], 3 | "customer_names": ["", "customer-name-four>"] 4 | } -------------------------------------------------------------------------------- /msp_customer_onboarding/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /msp_customer_onboarding/media/script_terminal_output_auto_licensing.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/msp_customer_onboarding/media/script_terminal_output_auto_licensing.gif -------------------------------------------------------------------------------- /msp_customer_onboarding/media/script_terminal_output_without_auto_subscription.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/msp_customer_onboarding/media/script_terminal_output_without_auto_subscription.gif -------------------------------------------------------------------------------- /msp_customer_onboarding/media/workflow_overview.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/msp_customer_onboarding/media/workflow_overview.png -------------------------------------------------------------------------------- /msp_customer_onboarding/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | colorama==0.4.6 4 | colored==2.2.3 5 | halo==0.0.31 6 | idna==3.7 7 | log-symbols==0.0.14 8 | pycentral==1.4.1 9 | PyYAML==6.0.1 10 | requests==2.31.0 11 | six==1.16.0 12 | spinners==0.0.24 13 | termcolor==2.3.0 14 | urllib3==2.2.2 -------------------------------------------------------------------------------- /msp_customer_onboarding/workflow_variables_auto_subscription.json: -------------------------------------------------------------------------------- 1 | { 2 | "customer_details": { 3 | "customer_name": "", 4 | "group_name": "", 5 | "street_address": "", 6 | "city": "", 7 | "state": "", 8 | "zip_postal_code": "", 9 | "country": "", 10 | "description": "", 11 | "lock_msp_ssids": "" 12 | }, 13 | "auto_subscription": [ 14 | "", 15 | "", 16 | "" 17 | ], 18 | "device_details": { 19 | "SWITCH": { 20 | "": { 21 | "mac_address": "" 22 | } 23 | }, 24 | "IAP": { 25 | "": { 26 | "mac_address": "" 27 | } 28 | } 29 | }, 30 | "site_details": { 31 | "site_name": "", 32 | "site_address": { 33 | "address": "", 34 | "city": "", 35 | "state": "", 36 | "country": "", 37 | "zipcode": "" 38 | } 39 | } 40 | } -------------------------------------------------------------------------------- /msp_customer_onboarding/workflow_variables_without_auto_subscription.json: -------------------------------------------------------------------------------- 1 | { 2 | "customer_details": { 3 | "customer_name": "", 4 | "group_name": "", 5 | "street_address": "", 6 | "city": "", 7 | "state": "", 8 | "zip_postal_code": "", 9 | "country": "", 10 | "description": "", 11 | "lock_msp_ssids": "" 12 | }, 13 | "device_details": { 14 | "SWITCH": { 15 | "": { 16 | "mac_address": "", 17 | "central_subscription": "" 18 | } 19 | }, 20 | "IAP": { 21 | "": { 22 | "mac_address": "", 23 | "central_subscription": "" 24 | } 25 | } 26 | }, 27 | "site_details": { 28 | "site_name": "", 29 | "site_address": { 30 | "address": "", 31 | "city": "", 32 | "state": "", 33 | "country": "", 34 | "zipcode": "" 35 | } 36 | } 37 | } -------------------------------------------------------------------------------- /renaming_aps/README.md: -------------------------------------------------------------------------------- 1 | # Renaming APs 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) library to achieve the following steps on an Aruba Central account- 3 | 1. Copy AP configuration 4 | 2. Change AP hostname 5 | 3. Replace old AP configuration with new AP configuration that has the new hostname 6 | 7 | ## Prerequisite 8 | 1. All Access Points have valid Central licenses before the workflow is run 9 | 2. Access Points are all online and configurable 10 | 3. Access Points do not need to be in the same group 11 | 12 | ## Installation Steps 13 | In order to run the script, please complete the steps below: 14 | 1. Clone this repository and `cd` into the workflow directory: 15 | ```bash 16 | git clone https://github.com/aruba/central-python-workflows 17 | cd central-python-workflows/renaming_aps 18 | ``` 19 | 20 | 2. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 21 | ```bash 22 | python -m venv env 23 | ``` 24 | 25 | 3. Activate the virtual environment 26 | In Mac/Linux: 27 | ```bash 28 | source env/bin/activate 29 | ``` 30 | In Windows: 31 | ```bash 32 | env/Scripts/activate.bat 33 | ``` 34 | 35 | 4. Install the packages required for the script 36 | ```bash 37 | python -m pip install -r requirements.txt 38 | ``` 39 | 40 | 5. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 41 | ```json 42 | { 43 | "central_info": { 44 | "base_url": "", 45 | "token": { 46 | "access_token": "" 47 | } 48 | }, 49 | "ssl_verify": true 50 | } 51 | ``` 52 | **Note** 53 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 54 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 55 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 56 | 57 | 6. Update the [variables_sample.csv] (variables_sample.csv is the default csv file) with AP serial numbers and new names OR create a custom csv of the same format to be used as an argument when executing the script 58 | ```csv 59 | sys_serial,new_name 60 | {ap1_serial_number},{ap1_new_name} 61 | {ap2_serial_number},{ap2_new_name} 62 | ``` 63 | 64 | 7. Once **central_token.json** & **variables_sample.csv** are updated with the relevant information, you can execute the script with the following command: 65 | ```bash 66 | python renaming_aps.py 67 | ``` 68 | **Note** 69 | - This script takes the following optional parameters to overide default filenames for the script 70 | - central_auth - Path of Central Token File 71 | - csv_names - Path of CSV Names File with AP serial numbers and new names (if no csv is specified the default variables_sample.csv file will be used) 72 | - You can run the following command to use the optional parameters - 73 | ```bash 74 | python renaming_aps.py --central_auth --csv_names 75 | ``` 76 | 77 | 8. If the script runs successfully, your terminal output should look like this - 78 |

79 | 80 |

81 | 82 | 9. An [output.csv] file will be created with the output of the script results 83 | - Columns will consist of: serial_number, old_name, new_name, status 84 | - The status variable shows whether or not the AP was successfully renamed 85 | ```csv 86 | serial_number,old_name,new_name,status 87 | {ap1_serial_number},{ap1_old_name},{ap1_new_name},success 88 | {ap2_serial_number},{ap2_old_name},{ap2_new_name},failure 89 | ``` 90 | 91 | ## Central APIs used for this workflow - 92 | 1. [Get Per AP Setting](https://developer.arubanetworks.com/aruba-central/reference/apiap_clisget_ap_settings_clis) 93 | 2. [Replace Per AP Setting](https://developer.arubanetworks.com/aruba-central/reference/apiap_clisupdate_ap_settings_clis) -------------------------------------------------------------------------------- /renaming_aps/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } 10 | -------------------------------------------------------------------------------- /renaming_aps/media/script_terminal_output.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/renaming_aps/media/script_terminal_output.gif -------------------------------------------------------------------------------- /renaming_aps/output.csv: -------------------------------------------------------------------------------- 1 | serial_number,old_name,new_name,status 2 | {ap1_serial_number},{ap1_old_name},{ap1_new_name},success 3 | {ap2_serial_number},{ap2_old_name},{ap2_new_name},failure 4 | -------------------------------------------------------------------------------- /renaming_aps/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.2.0 3 | colorama==0.4.6 4 | colored==2.2.3 5 | halo==0.0.31 6 | idna==3.7 7 | pycentral==1.0.0 8 | PyYAML==6.0.1 9 | requests==2.32.0 10 | six==1.16.0 11 | spinners==0.0.24 12 | termcolor==2.3.0 13 | urllib3==2.0.7 -------------------------------------------------------------------------------- /renaming_aps/variables.csv: -------------------------------------------------------------------------------- 1 | sys_serial,new_name 2 | {ap1_serial_number},{ap1_new_name} 3 | {ap2_serial_number},{ap2_new_name} -------------------------------------------------------------------------------- /renaming_aps/variables_sample.csv: -------------------------------------------------------------------------------- 1 | sys_serial,new_name 2 | {ap1_serial_number},{ap1_new_name} 3 | {ap2_serial_number},{ap2_new_name} -------------------------------------------------------------------------------- /streaming-api-client/input.json: -------------------------------------------------------------------------------- 1 | { 2 | "customers": { 3 | "": { 4 | "username": "", 5 | "wsskey": "", 6 | "topic": "" 7 | }, 8 | "": { 9 | "username": "", 10 | "wsskey": "", 11 | "topic": "" 12 | } 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /streaming-api-client/lib/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/streaming-api-client/lib/__init__.py -------------------------------------------------------------------------------- /streaming-api-client/lib/utilities.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2019 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import os 24 | import json 25 | import sys 26 | 27 | def parse_str(str, dict, sep=','): 28 | toks = str.split(sep) 29 | ret = 0 30 | for tok in toks: 31 | tok = tok.strip() 32 | tok = tok.lower() 33 | if tok in dict: 34 | ret = ret | dict[tok] 35 | return ret 36 | 37 | def read_jsonfile(filename): 38 | # Extract customer info from input JSON File 39 | jsondict = {} 40 | jsonfile = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 41 | filename) 42 | 43 | if os.path.isfile(jsonfile): 44 | with open(jsonfile, 'r') as infile: 45 | try: 46 | jsondict = json.load(infile) 47 | except Exception as err: 48 | sys.exit("Error in Input JSON file: %s" % str(err)) 49 | 50 | return jsondict 51 | else: 52 | sys.exit("Error: json input file not found. exiting...") 53 | 54 | def write_jsonfile(filename, jsondict): 55 | jsonfile = os.path.join(os.path.dirname(os.path.realpath(sys.argv[0])), 56 | filename) 57 | if os.path.isfile(filename): 58 | with open(filename, 'w') as outfile: 59 | json.dump(jsondict, outfile, indent=2) 60 | return True 61 | else: 62 | return False 63 | -------------------------------------------------------------------------------- /streaming-api-client/proto/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/aruba/central-python-workflows/f9c00b60df48d246c4ef5ec8ab659035505e92f5/streaming-api-client/proto/__init__.py -------------------------------------------------------------------------------- /streaming-api-client/proto/apprf.proto: -------------------------------------------------------------------------------- 1 | package Apprf; 2 | 3 | message mac_address 4 | { 5 | optional bytes addr = 1; 6 | } 7 | 8 | message ip_address 9 | { 10 | enum addr_family 11 | { 12 | ADDR_FAMILY_UNSPEC = 0; 13 | ADDR_FAMILY_INET = 1; 14 | ADDR_FAMILY_INET6 = 2; 15 | } 16 | optional addr_family af = 1; 17 | optional bytes addr = 2; 18 | } 19 | 20 | message apprf_session { 21 | 22 | optional string customer_id = 1; 23 | optional uint64 timestamp = 2; 24 | optional string serial_number = 3; 25 | repeated client_firewall_session client_firewall_session = 4; 26 | repeated url_detail_record url_detail_record = 5; 27 | optional string ap_name = 6; 28 | optional uint32 session_duration = 7; 29 | 30 | } 31 | 32 | 33 | 34 | message client_firewall_session { 35 | optional ip_address client_ip = 1; 36 | optional mac_address client_mac = 2; 37 | optional ip_address dest_ip = 3; 38 | optional ingress_type_t ingress_type = 4; 39 | enum ingress_type_t 40 | { 41 | INGRESS_WLAN = 0; 42 | INGRESS_WIRED = 1; 43 | INGRESS_VPN = 2; 44 | } 45 | optional uint32 ip_proto = 5; 46 | optional string vlan = 6; 47 | optional uint32 uplink_id = 7; 48 | optional string uplink_name = 8; 49 | optional uint32 app_id = 9; 50 | optional string app_name = 10; 51 | optional uint32 app_cat_id = 11; 52 | optional string app_cat = 12; 53 | optional uint32 web_cat_id = 13; 54 | optional string web_cat = 14; 55 | optional uint32 web_rep_score = 15; 56 | optional string web_rep = 16; 57 | optional string dest_url_prefix = 17; 58 | optional string domain = 18; 59 | enum app_enforcement_status 60 | { 61 | ENF_PERMIT = 0; 62 | ENF_DENY = 1; 63 | } 64 | optional app_enforcement_status session_flags = 19; 65 | optional uint64 tx_bytes = 20; 66 | optional uint64 rx_bytes = 21; 67 | optional uint64 rtt = 22; 68 | optional uint64 c2s_rtt = 23; 69 | optional uint64 s2c_rtt = 24; 70 | optional uint64 packet_loss = 25; 71 | optional uint64 c2s_packet_loss = 26; 72 | optional uint64 s2c_packet_loss = 27; 73 | optional string ssid = 28; 74 | optional string user_name = 29; 75 | optional string user_role = 30; 76 | optional string device_type = 31; 77 | optional uint64 timestamp = 32; 78 | optional bool preauth_flag = 33; 79 | optional uint32 dest_port = 34; 80 | } 81 | 82 | message url_detail_record { 83 | enum url_http_method 84 | { 85 | NON_HTTP = 1; 86 | HTTP_GET = 2; 87 | HTTP_PUT = 3; 88 | HTTP_POST = 4; 89 | HTTP_HEAD = 5; 90 | } 91 | required ip_address client_ip = 1; 92 | required ip_address dest_ip = 2; 93 | required mac_address client_mac = 3; 94 | optional bytes dest_url_prefix = 4; 95 | optional uint32 hit_count = 5; 96 | optional url_http_method http_method = 6; 97 | optional uint64 last_hit_timestamp = 7; 98 | } -------------------------------------------------------------------------------- /streaming-api-client/proto/apprf_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: apprf.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61pprf.proto\x12\x05\x41pprf\"\x1b\n\x0bmac_address\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x01(\x0c\"\x99\x01\n\nip_address\x12)\n\x02\x61\x66\x18\x01 \x01(\x0e\x32\x1d.Apprf.ip_address.addr_family\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\x0c\"R\n\x0b\x61\x64\x64r_family\x12\x16\n\x12\x41\x44\x44R_FAMILY_UNSPEC\x10\x00\x12\x14\n\x10\x41\x44\x44R_FAMILY_INET\x10\x01\x12\x15\n\x11\x41\x44\x44R_FAMILY_INET6\x10\x02\"\xef\x01\n\rapprf_session\x12\x13\n\x0b\x63ustomer_id\x18\x01 \x01(\t\x12\x11\n\ttimestamp\x18\x02 \x01(\x04\x12\x15\n\rserial_number\x18\x03 \x01(\t\x12?\n\x17\x63lient_firewall_session\x18\x04 \x03(\x0b\x32\x1e.Apprf.client_firewall_session\x12\x33\n\x11url_detail_record\x18\x05 \x03(\x0b\x32\x18.Apprf.url_detail_record\x12\x0f\n\x07\x61p_name\x18\x06 \x01(\t\x12\x18\n\x10session_duration\x18\x07 \x01(\r\"\xc2\x07\n\x17\x63lient_firewall_session\x12$\n\tclient_ip\x18\x01 \x01(\x0b\x32\x11.Apprf.ip_address\x12&\n\nclient_mac\x18\x02 \x01(\x0b\x32\x12.Apprf.mac_address\x12\"\n\x07\x64\x65st_ip\x18\x03 \x01(\x0b\x32\x11.Apprf.ip_address\x12\x43\n\x0cingress_type\x18\x04 \x01(\x0e\x32-.Apprf.client_firewall_session.ingress_type_t\x12\x10\n\x08ip_proto\x18\x05 \x01(\r\x12\x0c\n\x04vlan\x18\x06 \x01(\t\x12\x11\n\tuplink_id\x18\x07 \x01(\r\x12\x13\n\x0buplink_name\x18\x08 \x01(\t\x12\x0e\n\x06\x61pp_id\x18\t \x01(\r\x12\x10\n\x08\x61pp_name\x18\n \x01(\t\x12\x12\n\napp_cat_id\x18\x0b \x01(\r\x12\x0f\n\x07\x61pp_cat\x18\x0c \x01(\t\x12\x12\n\nweb_cat_id\x18\r \x01(\r\x12\x0f\n\x07web_cat\x18\x0e \x01(\t\x12\x15\n\rweb_rep_score\x18\x0f \x01(\r\x12\x0f\n\x07web_rep\x18\x10 \x01(\t\x12\x17\n\x0f\x64\x65st_url_prefix\x18\x11 \x01(\t\x12\x0e\n\x06\x64omain\x18\x12 \x01(\t\x12L\n\rsession_flags\x18\x13 \x01(\x0e\x32\x35.Apprf.client_firewall_session.app_enforcement_status\x12\x10\n\x08tx_bytes\x18\x14 \x01(\x04\x12\x10\n\x08rx_bytes\x18\x15 \x01(\x04\x12\x0b\n\x03rtt\x18\x16 \x01(\x04\x12\x0f\n\x07\x63\x32s_rtt\x18\x17 \x01(\x04\x12\x0f\n\x07s2c_rtt\x18\x18 \x01(\x04\x12\x13\n\x0bpacket_loss\x18\x19 \x01(\x04\x12\x17\n\x0f\x63\x32s_packet_loss\x18\x1a \x01(\x04\x12\x17\n\x0fs2c_packet_loss\x18\x1b \x01(\x04\x12\x0c\n\x04ssid\x18\x1c \x01(\t\x12\x11\n\tuser_name\x18\x1d \x01(\t\x12\x11\n\tuser_role\x18\x1e \x01(\t\x12\x13\n\x0b\x64\x65vice_type\x18\x1f \x01(\t\x12\x11\n\ttimestamp\x18 \x01(\x04\x12\x14\n\x0cpreauth_flag\x18! \x01(\x08\x12\x11\n\tdest_port\x18\" \x01(\r\"F\n\x0eingress_type_t\x12\x10\n\x0cINGRESS_WLAN\x10\x00\x12\x11\n\rINGRESS_WIRED\x10\x01\x12\x0f\n\x0bINGRESS_VPN\x10\x02\"6\n\x16\x61pp_enforcement_status\x12\x0e\n\nENF_PERMIT\x10\x00\x12\x0c\n\x08\x45NF_DENY\x10\x01\"\xe7\x02\n\x11url_detail_record\x12$\n\tclient_ip\x18\x01 \x02(\x0b\x32\x11.Apprf.ip_address\x12\"\n\x07\x64\x65st_ip\x18\x02 \x02(\x0b\x32\x11.Apprf.ip_address\x12&\n\nclient_mac\x18\x03 \x02(\x0b\x32\x12.Apprf.mac_address\x12\x17\n\x0f\x64\x65st_url_prefix\x18\x04 \x01(\x0c\x12\x11\n\thit_count\x18\x05 \x01(\r\x12=\n\x0bhttp_method\x18\x06 \x01(\x0e\x32(.Apprf.url_detail_record.url_http_method\x12\x1a\n\x12last_hit_timestamp\x18\x07 \x01(\x04\"Y\n\x0furl_http_method\x12\x0c\n\x08NON_HTTP\x10\x01\x12\x0c\n\x08HTTP_GET\x10\x02\x12\x0c\n\x08HTTP_PUT\x10\x03\x12\r\n\tHTTP_POST\x10\x04\x12\r\n\tHTTP_HEAD\x10\x05') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'apprf_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _MAC_ADDRESS._serialized_start=22 24 | _MAC_ADDRESS._serialized_end=49 25 | _IP_ADDRESS._serialized_start=52 26 | _IP_ADDRESS._serialized_end=205 27 | _IP_ADDRESS_ADDR_FAMILY._serialized_start=123 28 | _IP_ADDRESS_ADDR_FAMILY._serialized_end=205 29 | _APPRF_SESSION._serialized_start=208 30 | _APPRF_SESSION._serialized_end=447 31 | _CLIENT_FIREWALL_SESSION._serialized_start=450 32 | _CLIENT_FIREWALL_SESSION._serialized_end=1412 33 | _CLIENT_FIREWALL_SESSION_INGRESS_TYPE_T._serialized_start=1286 34 | _CLIENT_FIREWALL_SESSION_INGRESS_TYPE_T._serialized_end=1356 35 | _CLIENT_FIREWALL_SESSION_APP_ENFORCEMENT_STATUS._serialized_start=1358 36 | _CLIENT_FIREWALL_SESSION_APP_ENFORCEMENT_STATUS._serialized_end=1412 37 | _URL_DETAIL_RECORD._serialized_start=1415 38 | _URL_DETAIL_RECORD._serialized_end=1774 39 | _URL_DETAIL_RECORD_URL_HTTP_METHOD._serialized_start=1685 40 | _URL_DETAIL_RECORD_URL_HTTP_METHOD._serialized_end=1774 41 | # @@protoc_insertion_point(module_scope) 42 | -------------------------------------------------------------------------------- /streaming-api-client/proto/audit.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto2"; 2 | 3 | package Audit; 4 | 5 | message mac_address 6 | { 7 | optional bytes addr = 1; 8 | } 9 | 10 | message ip_address 11 | { 12 | enum addr_family 13 | { 14 | ADDR_FAMILY_UNSPEC = 0; 15 | ADDR_FAMILY_INET = 1; 16 | ADDR_FAMILY_INET6 = 2; 17 | } 18 | optional addr_family af = 1; 19 | optional bytes addr = 2; 20 | } 21 | 22 | enum classification { 23 | CONFIGURATION = 0; 24 | FIRMWARE = 1; 25 | DEVICE_MGMT = 2; 26 | } 27 | 28 | message config { 29 | required string data = 1; 30 | optional string detailed_data = 2; 31 | } 32 | 33 | message firmware { 34 | required string data = 1; 35 | optional string detailed_data = 2; 36 | } 37 | 38 | message device_management { 39 | required string data = 1; 40 | optional string detailed_data = 2; 41 | } 42 | 43 | message audit_message{ 44 | required string customer_id = 1; 45 | required uint32 timestamp = 2; 46 | required classification service = 3; 47 | required string group_name = 4; 48 | required string target = 5; //swarm_id, device_id 49 | required ip_address client_ip = 6; // User details 50 | required string username = 7; 51 | 52 | // Service data 53 | optional config config_info = 8; 54 | optional firmware firmware_info = 9; 55 | optional device_management dm_info = 16; 56 | } -------------------------------------------------------------------------------- /streaming-api-client/proto/audit_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: audit.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0b\x61udit.proto\x12\x05\x41udit\"\x1b\n\x0bmac_address\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x01(\x0c\"\x99\x01\n\nip_address\x12)\n\x02\x61\x66\x18\x01 \x01(\x0e\x32\x1d.Audit.ip_address.addr_family\x12\x0c\n\x04\x61\x64\x64r\x18\x02 \x01(\x0c\"R\n\x0b\x61\x64\x64r_family\x12\x16\n\x12\x41\x44\x44R_FAMILY_UNSPEC\x10\x00\x12\x14\n\x10\x41\x44\x44R_FAMILY_INET\x10\x01\x12\x15\n\x11\x41\x44\x44R_FAMILY_INET6\x10\x02\"-\n\x06\x63onfig\x12\x0c\n\x04\x64\x61ta\x18\x01 \x02(\t\x12\x15\n\rdetailed_data\x18\x02 \x01(\t\"/\n\x08\x66irmware\x12\x0c\n\x04\x64\x61ta\x18\x01 \x02(\t\x12\x15\n\rdetailed_data\x18\x02 \x01(\t\"8\n\x11\x64\x65vice_management\x12\x0c\n\x04\x64\x61ta\x18\x01 \x02(\t\x12\x15\n\rdetailed_data\x18\x02 \x01(\t\"\xb2\x02\n\raudit_message\x12\x13\n\x0b\x63ustomer_id\x18\x01 \x02(\t\x12\x11\n\ttimestamp\x18\x02 \x02(\r\x12&\n\x07service\x18\x03 \x02(\x0e\x32\x15.Audit.classification\x12\x12\n\ngroup_name\x18\x04 \x02(\t\x12\x0e\n\x06target\x18\x05 \x02(\t\x12$\n\tclient_ip\x18\x06 \x02(\x0b\x32\x11.Audit.ip_address\x12\x10\n\x08username\x18\x07 \x02(\t\x12\"\n\x0b\x63onfig_info\x18\x08 \x01(\x0b\x32\r.Audit.config\x12&\n\rfirmware_info\x18\t \x01(\x0b\x32\x0f.Audit.firmware\x12)\n\x07\x64m_info\x18\x10 \x01(\x0b\x32\x18.Audit.device_management*B\n\x0e\x63lassification\x12\x11\n\rCONFIGURATION\x10\x00\x12\x0c\n\x08\x46IRMWARE\x10\x01\x12\x0f\n\x0b\x44\x45VICE_MGMT\x10\x02') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'audit_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _CLASSIFICATION._serialized_start=670 24 | _CLASSIFICATION._serialized_end=736 25 | _MAC_ADDRESS._serialized_start=22 26 | _MAC_ADDRESS._serialized_end=49 27 | _IP_ADDRESS._serialized_start=52 28 | _IP_ADDRESS._serialized_end=205 29 | _IP_ADDRESS_ADDR_FAMILY._serialized_start=123 30 | _IP_ADDRESS_ADDR_FAMILY._serialized_end=205 31 | _CONFIG._serialized_start=207 32 | _CONFIG._serialized_end=252 33 | _FIRMWARE._serialized_start=254 34 | _FIRMWARE._serialized_end=301 35 | _DEVICE_MANAGEMENT._serialized_start=303 36 | _DEVICE_MANAGEMENT._serialized_end=359 37 | _AUDIT_MESSAGE._serialized_start=362 38 | _AUDIT_MESSAGE._serialized_end=668 39 | # @@protoc_insertion_point(module_scope) 40 | -------------------------------------------------------------------------------- /streaming-api-client/proto/location.proto: -------------------------------------------------------------------------------- 1 | package Location; 2 | 3 | 4 | message mac_address 5 | { 6 | optional bytes addr = 1; 7 | } 8 | 9 | enum target_dev_type 10 | { 11 | TARGET_TYPE_UNKNOWN = 0; 12 | TARGET_TYPE_STATION = 1; 13 | TARGET_TYPE_TAG = 2; 14 | TARGET_TYPE_ROGUE = 3; 15 | } 16 | 17 | enum algorithm 18 | { 19 | ALGORITHM_TRIANGULATION = 0; 20 | ALGORITHM_AP_PLACEMENT = 1; 21 | ALGORITHM_CALIBRATION = 2; 22 | ALGORITHM_ESTIMATION = 3; 23 | ALGORITHM_LOW_DENSITY = 4; 24 | } 25 | 26 | enum measurement_unit 27 | { 28 | METERS = 0; 29 | FEET = 1; 30 | PIXELS = 2; 31 | } 32 | 33 | message record { 34 | required uint32 timestamp = 1; 35 | required mac_address radio_mac = 2; 36 | required int32 rssi_val = 3; 37 | optional uint32 channel = 4; 38 | } 39 | 40 | enum error_code { 41 | ERROR_CODE_NO_ERROR = 0; // No error (a new fix is available) 42 | ERROR_CODE_0_RSSI = 1; // 0 RSSI could be used with the PDB 43 | ERROR_CODE_ONLY_1_RSSI = 2; // 1 RSSI could be used with the PDB 44 | ERROR_CODE_ONLY_2_RSSI = 3; // 2 RSSI could be used with the PDB 45 | ERROR_CODE_RSSI_QUALITY = 4; // RSSIs measurement are poor quality 46 | ERROR_CODE_RSSI_OLD_TIMESTAMP = 8; // timestamps of RSSI is too old 47 | ERROR_CODE_RSSI_CLOSE_TIMESTAMP = 16; // time since last fix computed is under threshold 48 | ERROR_CODE_LEGACY = 0xFFFFF; // This is the legacy error code for ALE version < 2.0.0.15 (internal usage) 49 | } 50 | 51 | message stream_location 52 | { 53 | optional float sta_location_x = 1; 54 | optional float sta_location_y = 2; 55 | optional uint32 error_level = 3; 56 | optional string hashed_sta_eth_mac = 7; 57 | repeated string geofence_ids = 8; 58 | optional algorithm loc_algorithm = 9; 59 | optional double longitude = 11; 60 | optional double latitude = 12; 61 | optional double altitude = 13; 62 | optional measurement_unit unit = 14; 63 | required mac_address sta_eth_mac = 15; 64 | optional string campus_id_string = 16; 65 | optional string building_id_string = 17; 66 | optional string floor_id_string = 18; 67 | optional target_dev_type target_type = 19 [default=TARGET_TYPE_UNKNOWN]; 68 | optional bool associated = 20; 69 | optional error_code err_code = 21; 70 | repeated record records = 22; 71 | } 72 | 73 | enum zone_event { 74 | ZONE_IN = 0; 75 | ZONE_OUT = 1; 76 | } 77 | 78 | message stream_geofence_notify { 79 | optional zone_event geofence_event = 1; 80 | optional bytes geofence_id = 2; 81 | optional string geofence_name = 3; 82 | optional mac_address sta_eth_mac = 4; 83 | optional bool associated = 5; 84 | optional uint32 dwell_time = 6 [default=0]; 85 | optional string hashed_sta_eth_mac = 7; 86 | } 87 | -------------------------------------------------------------------------------- /streaming-api-client/proto/location_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: location.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf import descriptor as _descriptor 6 | from google.protobuf import descriptor_pool as _descriptor_pool 7 | from google.protobuf import symbol_database as _symbol_database 8 | from google.protobuf.internal import builder as _builder 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0elocation.proto\x12\x08Location\"\x1b\n\x0bmac_address\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x01(\x0c\"h\n\x06record\x12\x11\n\ttimestamp\x18\x01 \x02(\r\x12(\n\tradio_mac\x18\x02 \x02(\x0b\x32\x15.Location.mac_address\x12\x10\n\x08rssi_val\x18\x03 \x02(\x05\x12\x0f\n\x07\x63hannel\x18\x04 \x01(\r\"\xb4\x04\n\x0fstream_location\x12\x16\n\x0esta_location_x\x18\x01 \x01(\x02\x12\x16\n\x0esta_location_y\x18\x02 \x01(\x02\x12\x13\n\x0b\x65rror_level\x18\x03 \x01(\r\x12\x1a\n\x12hashed_sta_eth_mac\x18\x07 \x01(\t\x12\x14\n\x0cgeofence_ids\x18\x08 \x03(\t\x12*\n\rloc_algorithm\x18\t \x01(\x0e\x32\x13.Location.algorithm\x12\x11\n\tlongitude\x18\x0b \x01(\x01\x12\x10\n\x08latitude\x18\x0c \x01(\x01\x12\x10\n\x08\x61ltitude\x18\r \x01(\x01\x12(\n\x04unit\x18\x0e \x01(\x0e\x32\x1a.Location.measurement_unit\x12*\n\x0bsta_eth_mac\x18\x0f \x02(\x0b\x32\x15.Location.mac_address\x12\x18\n\x10\x63\x61mpus_id_string\x18\x10 \x01(\t\x12\x1a\n\x12\x62uilding_id_string\x18\x11 \x01(\t\x12\x17\n\x0f\x66loor_id_string\x18\x12 \x01(\t\x12\x43\n\x0btarget_type\x18\x13 \x01(\x0e\x32\x19.Location.target_dev_type:\x13TARGET_TYPE_UNKNOWN\x12\x12\n\nassociated\x18\x14 \x01(\x08\x12&\n\x08\x65rr_code\x18\x15 \x01(\x0e\x32\x14.Location.error_code\x12!\n\x07records\x18\x16 \x03(\x0b\x32\x10.Location.record\"\xe5\x01\n\x16stream_geofence_notify\x12,\n\x0egeofence_event\x18\x01 \x01(\x0e\x32\x14.Location.zone_event\x12\x13\n\x0bgeofence_id\x18\x02 \x01(\x0c\x12\x15\n\rgeofence_name\x18\x03 \x01(\t\x12*\n\x0bsta_eth_mac\x18\x04 \x01(\x0b\x32\x15.Location.mac_address\x12\x12\n\nassociated\x18\x05 \x01(\x08\x12\x15\n\ndwell_time\x18\x06 \x01(\r:\x01\x30\x12\x1a\n\x12hashed_sta_eth_mac\x18\x07 \x01(\t*o\n\x0ftarget_dev_type\x12\x17\n\x13TARGET_TYPE_UNKNOWN\x10\x00\x12\x17\n\x13TARGET_TYPE_STATION\x10\x01\x12\x13\n\x0fTARGET_TYPE_TAG\x10\x02\x12\x15\n\x11TARGET_TYPE_ROGUE\x10\x03*\x94\x01\n\talgorithm\x12\x1b\n\x17\x41LGORITHM_TRIANGULATION\x10\x00\x12\x1a\n\x16\x41LGORITHM_AP_PLACEMENT\x10\x01\x12\x19\n\x15\x41LGORITHM_CALIBRATION\x10\x02\x12\x18\n\x14\x41LGORITHM_ESTIMATION\x10\x03\x12\x19\n\x15\x41LGORITHM_LOW_DENSITY\x10\x04*4\n\x10measurement_unit\x12\n\n\x06METERS\x10\x00\x12\x08\n\x04\x46\x45\x45T\x10\x01\x12\n\n\x06PIXELS\x10\x02*\xf2\x01\n\nerror_code\x12\x17\n\x13\x45RROR_CODE_NO_ERROR\x10\x00\x12\x15\n\x11\x45RROR_CODE_0_RSSI\x10\x01\x12\x1a\n\x16\x45RROR_CODE_ONLY_1_RSSI\x10\x02\x12\x1a\n\x16\x45RROR_CODE_ONLY_2_RSSI\x10\x03\x12\x1b\n\x17\x45RROR_CODE_RSSI_QUALITY\x10\x04\x12!\n\x1d\x45RROR_CODE_RSSI_OLD_TIMESTAMP\x10\x08\x12#\n\x1f\x45RROR_CODE_RSSI_CLOSE_TIMESTAMP\x10\x10\x12\x17\n\x11\x45RROR_CODE_LEGACY\x10\xff\xff?*\'\n\nzone_event\x12\x0b\n\x07ZONE_IN\x10\x00\x12\x0c\n\x08ZONE_OUT\x10\x01') 17 | 18 | _globals = globals() 19 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, _globals) 20 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'location_pb2', _globals) 21 | if _descriptor._USE_C_DESCRIPTORS == False: 22 | DESCRIPTOR._options = None 23 | _globals['_TARGET_DEV_TYPE']._serialized_start=962 24 | _globals['_TARGET_DEV_TYPE']._serialized_end=1073 25 | _globals['_ALGORITHM']._serialized_start=1076 26 | _globals['_ALGORITHM']._serialized_end=1224 27 | _globals['_MEASUREMENT_UNIT']._serialized_start=1226 28 | _globals['_MEASUREMENT_UNIT']._serialized_end=1278 29 | _globals['_ERROR_CODE']._serialized_start=1281 30 | _globals['_ERROR_CODE']._serialized_end=1523 31 | _globals['_ZONE_EVENT']._serialized_start=1525 32 | _globals['_ZONE_EVENT']._serialized_end=1564 33 | _globals['_MAC_ADDRESS']._serialized_start=28 34 | _globals['_MAC_ADDRESS']._serialized_end=55 35 | _globals['_RECORD']._serialized_start=57 36 | _globals['_RECORD']._serialized_end=161 37 | _globals['_STREAM_LOCATION']._serialized_start=164 38 | _globals['_STREAM_LOCATION']._serialized_end=728 39 | _globals['_STREAM_GEOFENCE_NOTIFY']._serialized_start=731 40 | _globals['_STREAM_GEOFENCE_NOTIFY']._serialized_end=960 41 | # @@protoc_insertion_point(module_scope) 42 | -------------------------------------------------------------------------------- /streaming-api-client/proto/presence.proto: -------------------------------------------------------------------------------- 1 | package Presence; 2 | 3 | message mac_address { 4 | required bytes addr = 1; 5 | } 6 | 7 | message MacAddress { 8 | required bytes addr = 1; 9 | } 10 | 11 | //this message contains client_state information 12 | 13 | message presence_client_state { 14 | enum client_state { 15 | passerby = 0; 16 | visitor = 1; 17 | engaged = 2; 18 | }; 19 | 20 | optional bool is_label = 2; 21 | optional uint64 label_id = 3; 22 | optional uint64 label_category_id = 4; 23 | optional client_state state = 5; 24 | optional bool is_associated = 6; 25 | } 26 | 27 | 28 | 29 | //The message will have client state information generated by presence context 30 | 31 | message pa_client_state{ 32 | repeated presence_client_state presence_client_state = 1; 33 | } 34 | 35 | 36 | //this message contains proximity event, which is the strongest rssi record reported for a client of all the aps that heard the client. 37 | message pa_proximity_event{ 38 | repeated proximity proximity = 1; 39 | } 40 | 41 | message proximity { 42 | optional string device_id = 1; 43 | optional mac_address sta_eth_mac = 2; 44 | optional mac_address radio_mac = 3; 45 | optional int32 rssi_val = 4; 46 | optional uint32 noise_floor = 5; 47 | optional bool associated = 6; 48 | optional mac_address ap_eth_mac = 7; 49 | } 50 | 51 | //this message contains rssi event for a client 52 | 53 | message pa_rssi_event 54 | { 55 | repeated rssi rssi = 1; 56 | } 57 | 58 | message rssi { 59 | optional mac_address sta_eth_mac = 1; 60 | optional mac_address radio_mac = 2; 61 | optional int32 rssi_val = 3; 62 | optional uint32 noise_floor = 4; 63 | optional bool associated = 5; 64 | optional bool is_ap = 6; 65 | optional uint32 age = 7; 66 | optional string device_id = 8; 67 | optional mac_address ap_eth_mac = 9; 68 | } 69 | 70 | //this message contains presence events paylod 71 | message presence_event { 72 | enum presence_event_type { 73 | client_state = 0; 74 | rssi = 1; 75 | proximity = 2; 76 | } 77 | required uint64 timestamp = 1; 78 | required string customer_id = 2; 79 | required string event = 3; // 'presence' category 80 | required presence_event_type event_type = 4; // filter event 81 | optional pa_client_state pa_client_state = 5; 82 | optional pa_rssi_event pa_rssi_event = 6; 83 | optional pa_proximity_event pa_proximity_event = 7; 84 | } 85 | 86 | 87 | -------------------------------------------------------------------------------- /streaming-api-client/proto/presence_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: presence.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0epresence.proto\x12\x08Presence\"\x1b\n\x0bmac_address\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x02(\x0c\"\x1a\n\nMacAddress\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x02(\x0c\"\xe2\x01\n\x15presence_client_state\x12\x10\n\x08is_label\x18\x02 \x01(\x08\x12\x10\n\x08label_id\x18\x03 \x01(\x04\x12\x19\n\x11label_category_id\x18\x04 \x01(\x04\x12;\n\x05state\x18\x05 \x01(\x0e\x32,.Presence.presence_client_state.client_state\x12\x15\n\ris_associated\x18\x06 \x01(\x08\"6\n\x0c\x63lient_state\x12\x0c\n\x08passerby\x10\x00\x12\x0b\n\x07visitor\x10\x01\x12\x0b\n\x07\x65ngaged\x10\x02\"Q\n\x0fpa_client_state\x12>\n\x15presence_client_state\x18\x01 \x03(\x0b\x32\x1f.Presence.presence_client_state\"<\n\x12pa_proximity_event\x12&\n\tproximity\x18\x01 \x03(\x0b\x32\x13.Presence.proximity\"\xda\x01\n\tproximity\x12\x11\n\tdevice_id\x18\x01 \x01(\t\x12*\n\x0bsta_eth_mac\x18\x02 \x01(\x0b\x32\x15.Presence.mac_address\x12(\n\tradio_mac\x18\x03 \x01(\x0b\x32\x15.Presence.mac_address\x12\x10\n\x08rssi_val\x18\x04 \x01(\x05\x12\x13\n\x0bnoise_floor\x18\x05 \x01(\r\x12\x12\n\nassociated\x18\x06 \x01(\x08\x12)\n\nap_eth_mac\x18\x07 \x01(\x0b\x32\x15.Presence.mac_address\"-\n\rpa_rssi_event\x12\x1c\n\x04rssi\x18\x01 \x03(\x0b\x32\x0e.Presence.rssi\"\xf1\x01\n\x04rssi\x12*\n\x0bsta_eth_mac\x18\x01 \x01(\x0b\x32\x15.Presence.mac_address\x12(\n\tradio_mac\x18\x02 \x01(\x0b\x32\x15.Presence.mac_address\x12\x10\n\x08rssi_val\x18\x03 \x01(\x05\x12\x13\n\x0bnoise_floor\x18\x04 \x01(\r\x12\x12\n\nassociated\x18\x05 \x01(\x08\x12\r\n\x05is_ap\x18\x06 \x01(\x08\x12\x0b\n\x03\x61ge\x18\x07 \x01(\r\x12\x11\n\tdevice_id\x18\x08 \x01(\t\x12)\n\nap_eth_mac\x18\t \x01(\x0b\x32\x15.Presence.mac_address\"\xe9\x02\n\x0epresence_event\x12\x11\n\ttimestamp\x18\x01 \x02(\x04\x12\x13\n\x0b\x63ustomer_id\x18\x02 \x02(\t\x12\r\n\x05\x65vent\x18\x03 \x02(\t\x12@\n\nevent_type\x18\x04 \x02(\x0e\x32,.Presence.presence_event.presence_event_type\x12\x32\n\x0fpa_client_state\x18\x05 \x01(\x0b\x32\x19.Presence.pa_client_state\x12.\n\rpa_rssi_event\x18\x06 \x01(\x0b\x32\x17.Presence.pa_rssi_event\x12\x38\n\x12pa_proximity_event\x18\x07 \x01(\x0b\x32\x1c.Presence.pa_proximity_event\"@\n\x13presence_event_type\x12\x10\n\x0c\x63lient_state\x10\x00\x12\x08\n\x04rssi\x10\x01\x12\r\n\tproximity\x10\x02') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'presence_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _MAC_ADDRESS._serialized_start=28 24 | _MAC_ADDRESS._serialized_end=55 25 | _MACADDRESS._serialized_start=57 26 | _MACADDRESS._serialized_end=83 27 | _PRESENCE_CLIENT_STATE._serialized_start=86 28 | _PRESENCE_CLIENT_STATE._serialized_end=312 29 | _PRESENCE_CLIENT_STATE_CLIENT_STATE._serialized_start=258 30 | _PRESENCE_CLIENT_STATE_CLIENT_STATE._serialized_end=312 31 | _PA_CLIENT_STATE._serialized_start=314 32 | _PA_CLIENT_STATE._serialized_end=395 33 | _PA_PROXIMITY_EVENT._serialized_start=397 34 | _PA_PROXIMITY_EVENT._serialized_end=457 35 | _PROXIMITY._serialized_start=460 36 | _PROXIMITY._serialized_end=678 37 | _PA_RSSI_EVENT._serialized_start=680 38 | _PA_RSSI_EVENT._serialized_end=725 39 | _RSSI._serialized_start=728 40 | _RSSI._serialized_end=969 41 | _PRESENCE_EVENT._serialized_start=972 42 | _PRESENCE_EVENT._serialized_end=1333 43 | _PRESENCE_EVENT_PRESENCE_EVENT_TYPE._serialized_start=1269 44 | _PRESENCE_EVENT_PRESENCE_EVENT_TYPE._serialized_end=1333 45 | # @@protoc_insertion_point(module_scope) 46 | -------------------------------------------------------------------------------- /streaming-api-client/proto/security.proto: -------------------------------------------------------------------------------- 1 | package Security; 2 | 3 | enum Action { 4 | ADD = 1; 5 | DELETE = 2; 6 | UPDATE = 3; 7 | } 8 | 9 | message MacAddress { 10 | required bytes addr = 1; 11 | } 12 | 13 | message RapidsStreamingEvent { 14 | required string cust_id = 1; 15 | repeated RogueEvent rogue = 2; 16 | repeated WIDSEvent idsEvent = 3; 17 | } 18 | 19 | message RogueEvent { 20 | required MacAddress rogue_id = 1; 21 | required uint32 classification = 2; 22 | optional string first_seen = 3; 23 | optional string last_seen = 4; 24 | optional string rogue_name = 5; 25 | optional string ssid = 6; 26 | optional string lan_mac = 7; 27 | optional string first_det_device = 8; 28 | optional string last_det_device = 9; 29 | optional uint32 encryption = 10; 30 | optional string port = 11; 31 | optional string containment_status = 12; 32 | optional string mac_vendor = 13; 33 | } 34 | 35 | message WIDSEvent { 36 | required string device_id = 1; 37 | required uint32 event_number = 2; 38 | optional string event_type = 3; 39 | optional string attack_type = 4; 40 | optional string description = 5; 41 | optional string detected_ap = 6; 42 | optional MacAddress mac_addr = 7; 43 | optional string radio_band = 8; 44 | optional string level = 9; 45 | } 46 | -------------------------------------------------------------------------------- /streaming-api-client/proto/security_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: security.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0esecurity.proto\x12\x08Security\"\x1a\n\nMacAddress\x12\x0c\n\x04\x61\x64\x64r\x18\x01 \x02(\x0c\"s\n\x14RapidsStreamingEvent\x12\x0f\n\x07\x63ust_id\x18\x01 \x02(\t\x12#\n\x05rogue\x18\x02 \x03(\x0b\x32\x14.Security.RogueEvent\x12%\n\x08idsEvent\x18\x03 \x03(\x0b\x32\x13.Security.WIDSEvent\"\xab\x02\n\nRogueEvent\x12&\n\x08rogue_id\x18\x01 \x02(\x0b\x32\x14.Security.MacAddress\x12\x16\n\x0e\x63lassification\x18\x02 \x02(\r\x12\x12\n\nfirst_seen\x18\x03 \x01(\t\x12\x11\n\tlast_seen\x18\x04 \x01(\t\x12\x12\n\nrogue_name\x18\x05 \x01(\t\x12\x0c\n\x04ssid\x18\x06 \x01(\t\x12\x0f\n\x07lan_mac\x18\x07 \x01(\t\x12\x18\n\x10\x66irst_det_device\x18\x08 \x01(\t\x12\x17\n\x0flast_det_device\x18\t \x01(\t\x12\x12\n\nencryption\x18\n \x01(\r\x12\x0c\n\x04port\x18\x0b \x01(\t\x12\x1a\n\x12\x63ontainment_status\x18\x0c \x01(\t\x12\x12\n\nmac_vendor\x18\r \x01(\t\"\xd2\x01\n\tWIDSEvent\x12\x11\n\tdevice_id\x18\x01 \x02(\t\x12\x14\n\x0c\x65vent_number\x18\x02 \x02(\r\x12\x12\n\nevent_type\x18\x03 \x01(\t\x12\x13\n\x0b\x61ttack_type\x18\x04 \x01(\t\x12\x13\n\x0b\x64\x65scription\x18\x05 \x01(\t\x12\x13\n\x0b\x64\x65tected_ap\x18\x06 \x01(\t\x12&\n\x08mac_addr\x18\x07 \x01(\x0b\x32\x14.Security.MacAddress\x12\x12\n\nradio_band\x18\x08 \x01(\t\x12\r\n\x05level\x18\t \x01(\t*)\n\x06\x41\x63tion\x12\x07\n\x03\x41\x44\x44\x10\x01\x12\n\n\x06\x44\x45LETE\x10\x02\x12\n\n\x06UPDATE\x10\x03') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'security_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _ACTION._serialized_start=688 24 | _ACTION._serialized_end=729 25 | _MACADDRESS._serialized_start=28 26 | _MACADDRESS._serialized_end=54 27 | _RAPIDSSTREAMINGEVENT._serialized_start=56 28 | _RAPIDSSTREAMINGEVENT._serialized_end=171 29 | _ROGUEEVENT._serialized_start=174 30 | _ROGUEEVENT._serialized_end=473 31 | _WIDSEVENT._serialized_start=476 32 | _WIDSEVENT._serialized_end=686 33 | # @@protoc_insertion_point(module_scope) 34 | -------------------------------------------------------------------------------- /streaming-api-client/proto/streaming.proto: -------------------------------------------------------------------------------- 1 | syntax = "proto3"; 2 | package StreamMessage; 3 | 4 | message MsgProto { 5 | string subject = 2; // subject 6 | bytes data = 3; // payload 7 | int64 timestamp = 4; // received timestamp 8 | string customer_id = 5; // customer id to which this data belongs 9 | string msp_id = 6; // optional field indicating the msp_id 10 | } -------------------------------------------------------------------------------- /streaming-api-client/proto/streaming_pb2.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | # Generated by the protocol buffer compiler. DO NOT EDIT! 3 | # source: streaming.proto 4 | """Generated protocol buffer code.""" 5 | from google.protobuf.internal import builder as _builder 6 | from google.protobuf import descriptor as _descriptor 7 | from google.protobuf import descriptor_pool as _descriptor_pool 8 | from google.protobuf import symbol_database as _symbol_database 9 | # @@protoc_insertion_point(imports) 10 | 11 | _sym_db = _symbol_database.Default() 12 | 13 | 14 | 15 | 16 | DESCRIPTOR = _descriptor_pool.Default().AddSerializedFile(b'\n\x0fstreaming.proto\x12\rStreamMessage\"a\n\x08MsgProto\x12\x0f\n\x07subject\x18\x02 \x01(\t\x12\x0c\n\x04\x64\x61ta\x18\x03 \x01(\x0c\x12\x11\n\ttimestamp\x18\x04 \x01(\x03\x12\x13\n\x0b\x63ustomer_id\x18\x05 \x01(\t\x12\x0e\n\x06msp_id\x18\x06 \x01(\tb\x06proto3') 17 | 18 | _builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals()) 19 | _builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, 'streaming_pb2', globals()) 20 | if _descriptor._USE_C_DESCRIPTORS == False: 21 | 22 | DESCRIPTOR._options = None 23 | _MSGPROTO._serialized_start=34 24 | _MSGPROTO._serialized_end=131 25 | # @@protoc_insertion_point(module_scope) 26 | -------------------------------------------------------------------------------- /streaming-api-client/requirements.txt: -------------------------------------------------------------------------------- 1 | gevent 2 | greenlet 3 | protobuf 4 | six 5 | requests 6 | websocket 7 | websocket-client 8 | -------------------------------------------------------------------------------- /streaming-api-client/simple_app.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2019 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import websocket 24 | import _thread 25 | import time 26 | from proto import streaming_pb2 27 | 28 | def on_message(ws, message): 29 | # Decode Message in Serialized protobuffer 30 | stream_data = streaming_pb2.MsgProto() 31 | stream_data.ParseFromString(message) 32 | print("Timestamp in Epoch: %s" % str(stream_data.timestamp)) 33 | print("Customer_ID: %s" % str(stream_data.customer_id)) 34 | # Based on the topic import compiled proto file and decode 'data' field 35 | from proto import monitoring_pb2 36 | monitoring_data = monitoring_pb2.MonitoringInformation() 37 | monitoring_data.ParseFromString(stream_data.data) 38 | 39 | print(monitoring_data) 40 | 41 | def on_error(ws, error): 42 | print(error) 43 | 44 | def on_close(ws): 45 | print("### closed ###") 46 | 47 | def on_open(ws): 48 | def run(*args): 49 | print("Start Streaming Data!") 50 | _thread.start_new_thread(run, ()) 51 | 52 | 53 | if __name__ == "__main__": 54 | # URL for WebSocket Connection from Streaming API page 55 | hostname = "internal-ui.central.arubanetworks.com" 56 | url = "wss://{}/streaming/api".format(hostname) 57 | # Construct Header for WebSocket Connection 58 | header = {} 59 | # Central User email 60 | header["UserName"] = "abc@gmail.com" 61 | # WebSocket Key from Streaming API Page 62 | header["Authorization"] = "XXXXXX" 63 | # Subscription TOPIC for Streaming API 64 | # (audit|apprf|location|monitoring|presence|security) 65 | header["Topic"] = "monitoring" 66 | # Create WebSocket connection 67 | websocket.enableTrace(True) 68 | ws = websocket.WebSocketApp(url=url, 69 | header=header, 70 | on_message = on_message, 71 | on_error = on_error, 72 | on_close = on_close) 73 | ws.on_open = on_open 74 | ws.run_forever() 75 | -------------------------------------------------------------------------------- /user_provisioning/README.md: -------------------------------------------------------------------------------- 1 | # User Provisioning 2 | This is a Python script that uses the [Pycentral](https://pypi.org/project/pycentral/) to simplify the process of adding users and assigning roles to these users withing the HPE Greenlake Platform & Aruba Central. With this script, network admins can seamlessly onboard new users, configure their roles & ensure the users have the right access level. 3 | 4 | ## Prerequisite 5 | 1. The users being added are new to the GLCP platform and Central account. They don't have any existing roles in any accounts in GLCP. 6 | 7 | ## Installation Steps 8 | 1. Install virtual environment (refer https://docs.python.org/3/library/venv.html). Make sure python version 3 is installed in system. 9 | ```bash 10 | python -m venv env 11 | ``` 12 | 13 | 2. Activate the virtual environment 14 | In Mac/Linux: 15 | ```bash 16 | source env/bin/activate 17 | ``` 18 | In Windows: 19 | ```bash 20 | env/Scripts/activate.bat 21 | ``` 22 | 23 | 3. Install the packages required for the script 24 | ```bash 25 | python -m pip install -r requirements.txt 26 | ``` 27 | 4. There are three files required for the script 28 | 1. Provide the Central API Gateway Base URL & Access Token in the [central_token.json](central_token.json) 29 | ```json 30 | { 31 | "central_info": { 32 | "base_url": "", 33 | "token": { 34 | "access_token": "" 35 | } 36 | }, 37 | "ssl_verify": true 38 | } 39 | ``` 40 | **Note** 41 | - [BaseURLs of Aruba Central Clusters](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token#table-domain-urls-for-api-gateway-access) 42 | - [Generating Access token from Central UI](https://developer.arubanetworks.com/aruba-central/docs/api-gateway-creating-application-token) 43 | - [Generating Access token using OAuth APIs](https://developer.arubanetworks.com/aruba-central/docs/api-oauth-access-token) 44 | 2. This is a CSV file that has the following columns - 45 | 1. Email 46 | 2. First Name 47 | 3. Last Name 48 | 4. Password, 49 | 5. Country (2 Digit Code of Country) 50 | 6. Zip-code 51 | - All 6 columns are required for a user. 52 | 3. The roles that will be provided to the user is defined in the JSON file. 2 roles are required for each user. One role for each app, i.e. GLCP(account_setting) and Aruba Central(nms). 53 | - For example, the example [user_roles.json](user_roles.json) will provide the users with the following roles - 54 | 1. GLCP - Observer 55 | 2. Aruba Central - View Only (For all groups) 56 | - If you need to make changes to the roles that the script will assign to the user, please do so in the [user_roles.json](user_roles.json) file. 57 | 5. Once all the required files are ready, you can run the script. 58 | ```bash 59 | python3 user_provisioning.py --central_auth central_token.json --user_list_csv user_list.csv --user_role_json user_roles.json 60 | ``` 61 | - If you want to change the name of any of the required files, you can do it. Please be sure to update the python command with the updated file names when do so 62 | 6. Once the script is executed, it will create [script_output.csv](script_output.csv) that will indicate whether it was able to successfully add the user to the Central account. This CSV file will have the following columns 63 | 1. Email -> Email ID of User 64 | 2. Added_User -> Indicates whether user was added to Central account 65 | 66 | ## Central APIs used for this workflow - 67 | [Create a user account](https://developer.arubanetworks.com/aruba-central/reference/apiusercreate_user_account) -------------------------------------------------------------------------------- /user_provisioning/central_token.json: -------------------------------------------------------------------------------- 1 | { 2 | "central_info": { 3 | "base_url": "", 4 | "token": { 5 | "access_token": "" 6 | } 7 | }, 8 | "ssl_verify": true 9 | } -------------------------------------------------------------------------------- /user_provisioning/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | idna==3.7 4 | pycentral==1.4.1 5 | PyYAML==6.0.1 6 | requests==2.32.0 7 | termcolor==2.3.0 8 | urllib3==2.2.2 9 | -------------------------------------------------------------------------------- /user_provisioning/script_output.csv: -------------------------------------------------------------------------------- 1 | Email,Added_User 2 | abc@xyz.com,Success 3 | def@xyz.com,Failed -------------------------------------------------------------------------------- /user_provisioning/user_list.csv: -------------------------------------------------------------------------------- 1 | Email,First Name,Last Name,Password,Country,Zip-code 2 | abc@xyz.com,UserFirstName,UserLastName,Password,US,12345 3 | def@xyz.com,UserFirstName,UserLastName,Password,US,12345 -------------------------------------------------------------------------------- /user_provisioning/user_provisioning.py: -------------------------------------------------------------------------------- 1 | from argparse import ArgumentParser 2 | from csv import DictReader, DictWriter 3 | import sys 4 | import json 5 | from pycentral.workflows.workflows_utils import get_conn_from_file 6 | from termcolor import colored 7 | from time import sleep 8 | 9 | DELAY = 60 10 | REQUIRED_HEADERS = ['Email', 'First Name', 'Last Name', 'Password', 'Country', 'Zip-code'] 11 | REQUIRED_ROLES = ['nms', 'account_settings'] 12 | 13 | 14 | def main(): 15 | # Define Command-line Arguments 16 | args = define_arguments() 17 | 18 | # Get instance of ArubaCentralBase from the central_filename 19 | central = get_conn_from_file(filename=args.central_auth) 20 | 21 | user_list = read_user_list_csv(args.user_list_csv) 22 | 23 | user_role = read_roles_json(args.user_role_json) 24 | 25 | for user in user_list: 26 | user['Added_User'] = create_user(central, user, user_role) 27 | sleep(DELAY) 28 | export_csv(user_list, 'script_output.csv') 29 | 30 | 31 | def define_arguments(): 32 | """This function defines the command line arguments that can be used with this PyCentral script 33 | 34 | Returns: 35 | argparse.Namespace: Returns argparse namespace with central authorization & workflow variables file names 36 | """ 37 | 38 | description = 'This script takes a CSV file with user list and adds them to GLCP & Central with the provided roles.' 39 | 40 | parser = ArgumentParser(description=description) 41 | parser.add_argument( 42 | '--central_auth', 43 | help=('Central API Authorization file path'), 44 | default='central_token.json', 45 | required=True) 46 | parser.add_argument( 47 | '--user_list_csv', help=('List of users to be invited to Central'), 48 | default='user_list.csv', 49 | required=True) 50 | parser.add_argument( 51 | "--user_role_json", 52 | help=('GLCP & Central Role that should be assigned to each user'), 53 | required=True) 54 | return parser.parse_args() 55 | 56 | 57 | def read_user_list_csv(csv_filename): 58 | csv_list = [] 59 | with open(csv_filename, 'r') as f: 60 | dict_reader = DictReader(f) 61 | csv_list = list(dict_reader) 62 | if len(csv_list) == 0: 63 | sys.exit('Please provide a valid CSV file') 64 | for user in csv_list: 65 | for key in REQUIRED_HEADERS: 66 | if (key not in user): 67 | sys.exit(f'Please provide {colored(key, "red")} key-value in CSV file') 68 | elif isinstance(user[key], type(None)) or len(user[key]) == 0: 69 | sys.exit(f'Please provide a valid value for {colored(key, "red")} in CSV file.') 70 | return csv_list 71 | 72 | 73 | def read_roles_json(json_filename): 74 | roles_json = json.loads(open(json_filename, "r").read()) 75 | for role in REQUIRED_ROLES: 76 | if role not in list(roles_json.keys()): 77 | sys.exit(f'Missing required key {colored(role, "red")} in {json_filename}') 78 | return roles_json["roles"] 79 | 80 | 81 | def create_user(central_conn, user_data, role_details): 82 | apiPath = "/platform/rbac/v1/users" 83 | apiMethod = "POST" 84 | added_user = "Failed" 85 | apiData = { 86 | "username": user_data['Email'], 87 | "description": "", 88 | "password": user_data['Password'], 89 | "name": { 90 | "firstname": user_data['First Name'], 91 | "lastname": user_data['Last Name'] 92 | }, 93 | "phone": "", 94 | "address": { 95 | "country": user_data['Country'], 96 | "zipcode": user_data['Zip-code'] 97 | }, 98 | "applications": create_application_dict(role_details) 99 | } 100 | resp = central_conn.command(apiMethod=apiMethod, 101 | apiPath=apiPath, apiData=apiData) 102 | if resp['code'] == 200: 103 | print( 104 | f"Successfully added {colored(user_data['Email'], 'green')} to Central account.") 105 | added_user = "Success" 106 | else: 107 | print( 108 | f"ERROR - RESPONSE CODE({resp['code']}) \nUnable to add {colored(user_data['Email'], 'red')} to Central account.") 109 | return added_user 110 | 111 | 112 | def create_application_dict(user_roles): 113 | user_roles_obj = [] 114 | for role in REQUIRED_ROLES: 115 | user_role = user_roles[role] 116 | user_role_dict = { 117 | "name": user_role['app'], 118 | "info": [ 119 | { 120 | "role": user_role['role'] 121 | } 122 | ] 123 | } 124 | if "scope" in user_role: 125 | user_role_dict["info"][0]["scope"] = user_role["scope"] 126 | user_roles_obj.append(user_role_dict) 127 | return user_roles_obj 128 | 129 | 130 | def export_csv(user_list, export_file_name): 131 | selected_keys = ['Email', 'Added_User'] 132 | filtered_user_list = [dict((key, value) for key, value in user.items() 133 | if key in selected_keys) for user in user_list] 134 | header = filtered_user_list[0].keys() 135 | with open(export_file_name, 'w', newline='') as output_file: 136 | dict_writer = DictWriter(output_file, header) 137 | dict_writer.writeheader() 138 | dict_writer.writerows(filtered_user_list) 139 | 140 | 141 | if __name__ == "__main__": 142 | main() 143 | -------------------------------------------------------------------------------- /user_provisioning/user_roles.json: -------------------------------------------------------------------------------- 1 | { 2 | "nms": { 3 | "role": "Aruba Central View Only", 4 | "scope": { 5 | "groups": [ 6 | "allgroups" 7 | ] 8 | } 9 | }, 10 | "account_setting": { 11 | "role": "Observer" 12 | } 13 | } -------------------------------------------------------------------------------- /webhooks/python-webclient/README.md: -------------------------------------------------------------------------------- 1 | # Client Application for Aruba Central Webhooks 2 | 3 | ### **[Download as Zip File](https://downgit.github.io/#/home?url=https://github.com/aruba/central-examples-only/tree/master/webhooks/python-webclient)** 4 | 5 | Webhooks allow you to implement event reactions by providing real-time information or notifications to other applications. Aruba Central allows you to create [Webhooks](https://help.central.arubanetworks.com/latest/documentation/online_help/content/api/api_webhook.htm) and select them as the notification delivery option for all [Alerts & Events](https://help.central.arubanetworks.com/latest/documentation/online_help/content/nms/alerts/alerts.htm). When an Alert is configured with Webhook, the notification for the Alert will be pushed to the Webhook URL via HTTP POST from Aruba Central. 6 | 7 | The purpose of the sample python based HTTP(s) client application is to act as a reference on how to securely receive data from Aruba Central via Webhooks. This is not a production quality code and to be used under your sole discretion. 8 | 9 | Some use cases would be to integrate with external applications for automated ticket filing, push notifications in workspace communication tool such as Slack/Teams, build your own dashboard to monitor alerts and more. 10 | 11 | ## About "central_webhook_client.py" 12 | 13 | The script is verified to work with **Python version 3+**. 14 | 15 | ### Pre-Requisites 16 | 17 | Host this web client application in your preferred method. One way to run this script is to have the following 18 | 19 | - Webserver with FQDN/IP reachable from Aruba Central. Some of the most popular webservers are [Apache](https://httpd.apache.org/) / [Nginx](https://www.nginx.com/). 20 | 21 | - Configure reverse proxy in Webserver 22 | 23 | Sample reverse proxy configuration for Nginx webserver. Let us consider "https://www.example.com" as webserver FQDN. Upon applying this configuration, when the webserver receives the HTTP request from Aruba Central with the Webhook URL "https://www.example.com/centralwebhook", the webserver will act as a reverse proxy and forward the request to the mentioned upstream server IP address and the port (port 8010 in this example). The sample web client application should run on this upstream IP address and the port. 24 | 25 | ``` 26 | 27 | upstream centralwebhook { 28 | server 127.0.0.1:8010; 29 | } 30 | 31 | server { 32 | listen 443 default_server; 33 | listen [::]:443 default_server; 34 | server_name _; 35 | 36 | ... 37 | 38 | location /centralwebhook { 39 | proxy_pass http://centralwebhook; 40 | proxy_redirect off; 41 | proxy_set_header Host $host; 42 | } 43 | ``` 44 | 45 | - Create Webhooks in the Aruba Central by following the steps [mentioned here](https://help.central.arubanetworks.com/latest/documentation/online_help/content/api/api_webhook.htm#). The URL will be the FQDN/IP where webserver will host this sample web application. 46 | 47 | ### Script Execution 48 | 49 | Provide required information in the `input_info.json` 50 | 51 | ``` 52 | { 53 | "webclient_info": { 54 | "host": "localhost", 55 | "port": "" 56 | }, 57 | "central_info": { 58 | "webhook": { "name": "", 59 | "token": "" 60 | } 61 | } 62 | } 63 | ``` 64 | 65 | - *free-port-in-host* is the port of your choice where the sample client application will run in the localhost upon execution. 66 | 67 | - *name-of-the-webhook* is the name for the webhook in Aruba Central. This is optional and exists for your reference. 68 | 69 | - *token-of-the-webhook* can be obtained from `ACCOUNT HOME -> GLOBAL SETTINGS -> WEBHOOKS -> Click on the edit icon of your webhook -> Copy the "Token" value`. For added security, this token value can also be refreshed when required by the user by following the steps mentioned in the [guide](https://help.central.arubanetworks.com/latest/documentation/online_help/content/api/api_webhook.htm#). 70 | 71 | Command to execute the script: 72 | 73 | ``` 74 | python3 central_webhook_client.py -i=input_info.json 75 | ``` 76 | 77 | ### Validating authenticity and integrity of the received data 78 | 79 | The header of the received HTTP request from Aruba Central Webhook contains `X-Central-Signature`. This should be compared against the signature found by using HMAC algorithm and SHA256 hashing of the received data and webhook token in the input file as secret key. Refer the function `verifyHeaderAuth()` defined in the script on how to achieve this. 80 | 81 | If the signature obtained from HMAC algorithm is same as the X-Central-Signature in the header, both the integrity and the authenticity of the data are simultaneously considered verified. 82 | -------------------------------------------------------------------------------- /webhooks/python-webclient/central_webhook_client.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2020 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in all 13 | # copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | import base64 24 | import hashlib 25 | import hmac 26 | import json 27 | from http.server import HTTPServer, BaseHTTPRequestHandler 28 | from argparse import ArgumentParser, RawDescriptionHelpFormatter 29 | 30 | def define_arguments(): 31 | description = ("This is a HTTP client application for Aruba Central Webhook") 32 | parser = ArgumentParser(description=description, 33 | formatter_class=RawDescriptionHelpFormatter) 34 | parser.add_argument('-i', '--input', required=True, 35 | help=('Input file in JSON format which has central' 36 | 'as required by this script.')) 37 | return parser.parse_args() 38 | 39 | def verifyHeaderAuth(header, data): 40 | """ 41 | This method ensures integrity and authenticity of the data 42 | received from Aruba Central via Webhooks 43 | """ 44 | # Token obtained from Aruba Central Webhooks page as provided in the input 45 | token = input_args["central_info"]["webhook"]["token"] 46 | token = token.encode('utf-8') 47 | 48 | # Construct HMAC digest message 49 | sign_data = str(data) + header['X-Central-Service'] + \ 50 | header['X-Central-Delivery-Id'] + \ 51 | header['X-Central-Delivery-Timestamp'] 52 | sign_data = sign_data.encode('utf-8') 53 | 54 | # Find Message signature using HMAC algorithm and SHA256 digest mod 55 | dig = hmac.new(token, msg=sign_data, digestmod=hashlib.sha256).digest() 56 | signature = base64.b64encode(dig).decode() 57 | 58 | # Verify if the signature received in header is same as the one found using HMAC 59 | if header['X-Central-Signature'] == signature: 60 | return True 61 | return False 62 | 63 | class SimpleHTTPRequestHandler(BaseHTTPRequestHandler): 64 | """ 65 | This class handles HTTP requests 66 | """ 67 | def do_POST(self): 68 | """ 69 | Executed when POST Request is received 70 | """ 71 | body = self.rfile.read() 72 | self.send_response(200) 73 | self.end_headers() 74 | webhookData = body.decode('utf-8') 75 | 76 | # Ensure Authenticity of received message from Aruba Central 77 | if self.headers and "X-Central-Service" in self.headers: 78 | if verifyHeaderAuth(self.headers, webhookData): 79 | webhookData = json.loads(webhookData) 80 | print(json.dumps(webhookData, indent=2)) 81 | else: 82 | raise Exception ("Unable to verify authenticity & integrity " 83 | "of the data!!!") 84 | 85 | if __name__ == "__main__": 86 | # Gather information from args 87 | args = define_arguments() 88 | input_args = "" 89 | file_name = args.input 90 | with open(file_name, "r") as fp: 91 | input_args = json.loads(fp.read()) 92 | 93 | # host and port where this webclient runs 94 | host = input_args['webclient_info']['host'] 95 | port = int(input_args['webclient_info']['port']) 96 | 97 | # Start listening in the mentioned host and port 98 | httpd = HTTPServer((host, port), SimpleHTTPRequestHandler) 99 | httpd.serve_forever() 100 | -------------------------------------------------------------------------------- /webhooks/python-webclient/input_info.json: -------------------------------------------------------------------------------- 1 | { 2 | "webclient_info": { 3 | "host": "localhost", 4 | "port": "" 5 | }, 6 | "central_info": { 7 | "webhook": { "name": "", 8 | "token": "" 9 | } 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /wlan_config/configurations/README.md: -------------------------------------------------------------------------------- 1 | # Configurations 2 | This directory contains a collection of sample configuration files to be used with wlan_config workflow. 3 | Not all values are mandatory and can be adjusted depending on what the user needs. -------------------------------------------------------------------------------- /wlan_config/configurations/basic_sample.yaml: -------------------------------------------------------------------------------- 1 | # Sample for generating multiple personal wpa2 SSIDs using the basic wlan API. 2 | # This sample also demonstrates creating SSDIs at multiple targets. 3 | targets: 4 | - group1 5 | - group2 6 | wlans: 7 | - wlan: 8 | essid: ssid_workflow 9 | type: employee 10 | hide_ssid: true 11 | vlan: '10' 12 | zone: '1' 13 | wpa_passphrase: password 14 | wpa+passphrase_changed: true 15 | is_locked: true 16 | captive_profile_name: guest_profile 17 | bandwidth_limit_up: '34' 18 | bandwidth_limit_down: '25' 19 | bandwidth_limit_peruser_up: '45' 20 | bandwidth_limit_peruser_down: '34' 21 | access_rules: 22 | - action: allow 23 | netmask: 255.255.255.0 24 | protocol: tcp 25 | sport: '20' 26 | eport: '21' 27 | match: test.com 28 | service_name: bittorrent 29 | service_type: network 30 | throttle_upstream: '20' 31 | throttle_downstream: '25' 32 | - wlan: 33 | essid: ssid_workflow2 34 | type: employee 35 | hide_ssid: true 36 | vlan: '10' 37 | zone: '2' 38 | wpa_passphrase: password 39 | wpa+passphrase_changed: true 40 | is_locked: true 41 | captive_profile_name: guest_profile 42 | bandwidth_limit_up: '34' 43 | bandwidth_limit_down: '25' 44 | bandwidth_limit_peruser_up: '45' 45 | bandwidth_limit_peruser_down: '34' 46 | access_rules: 47 | - action: allow 48 | netmask: 255.255.255.0 49 | protocol: tcp 50 | sport: '20' 51 | eport: '21' 52 | match: test.com 53 | service_name: bittorrent 54 | service_type: network 55 | throttle_upstream: '20' 56 | throttle_downstream: '25' 57 | - wlan: 58 | essid: ssid_workflow3 59 | type: employee 60 | hide_ssid: true 61 | vlan: '10' 62 | zone: '3' 63 | wpa_passphrase: password 64 | wpa+passphrase_changed: true 65 | is_locked: true 66 | captive_profile_name: guest_profile 67 | bandwidth_limit_up: '34' 68 | bandwidth_limit_down: '25' 69 | bandwidth_limit_peruser_up: '45' 70 | bandwidth_limit_peruser_down: '34' 71 | access_rules: 72 | - action: allow 73 | netmask: 255.255.255.0 74 | protocol: tcp 75 | sport: '20' 76 | eport: '21' 77 | match: test.com 78 | service_name: bittorrent 79 | service_type: network 80 | throttle_upstream: '20' 81 | throttle_downstream: '25' 82 | -------------------------------------------------------------------------------- /wlan_config/configurations/delete_all.yaml: -------------------------------------------------------------------------------- 1 | # Sample for delete all workflow option. Add designated Central UI groupname that you want to delete all SSIDs from. 2 | targets: 3 | - group1 4 | - group2 5 | - group3 -------------------------------------------------------------------------------- /wlan_config/configurations/delete_sample.yaml: -------------------------------------------------------------------------------- 1 | # Add target Groupname, GUID, or Serial number to add SSID at. 2 | targets: 3 | - group1 4 | - group2 5 | # Add SSID's to be deleted in a list format 6 | delete_list: 7 | - ssid 8 | - ssid2 9 | - ssid3 10 | -------------------------------------------------------------------------------- /wlan_config/configurations/enhanced_captive.yaml: -------------------------------------------------------------------------------- 1 | # Sample for creating a generic enhanced open network with captive portal. 2 | targets: 3 | - groupname 4 | wlans: 5 | - wlan: 6 | access_type: unrestricted 7 | air_time_limit: "" 8 | air_time_limit_cb: false 9 | auth_server1: 'internal' 10 | auth_server2: '' 11 | auth_survivability: false 12 | bandwidth_limit: '' 13 | bandwidth_limit_cb: false 14 | blacklist: true 15 | broadcast_filter: arp 16 | called_station_id_deli: 0 17 | called_station_id_incl_ssid: false 18 | called_station_id_type: macaddr 19 | captive_exclude: [] 20 | captive_portal: {enable: true, value: external} 21 | captive_portal_proxy_ip: '' 22 | captive_portal_proxy_port: '' 23 | captive_profile_name: 'guest_user' 24 | cloud_guest: false 25 | cluster_name: '' 26 | content_filtering: false 27 | deny_intra_vlan_traffic: false 28 | disable_ssid: false 29 | dmo_channel_util_threshold: 90 30 | dot11k: false 31 | dot11v: false 32 | download_role: false 33 | dtim_period: 1 34 | dynamic_multicast_optimization: false 35 | dynamic_vlans: [] 36 | enforce_dhcp: false 37 | essid: captive-open 38 | explicit_ageout_client: false 39 | g_max_tx_rate: '54' 40 | g_min_tx_rate: '1' 41 | gw_profile_name: '' 42 | hide_ssid: false 43 | high_efficiency_disable: true 44 | high_throughput_disable: true 45 | inactivity_timeout: 1000 46 | index: 1 47 | l2_auth_failthrough: false 48 | l2switch_mode: false 49 | leap_use_session_key: false 50 | local_probe_req_threshold: 0 51 | mac_authentication: false 52 | mac_authentication_delimiter: '' 53 | mac_authentication_upper_case: false 54 | management_frame_protection: false 55 | max_auth_failures: 0 56 | max_clients_threshold: 64 57 | mdid: '' 58 | multicast_rate_optimization: false 59 | name: captive-open 60 | okc: false 61 | oos_def: vpn-down 62 | oos_name: none 63 | oos_time: 30 64 | opmode: enhanced-open 65 | opmode_transition_disable: true 66 | per_user_limit: 67 | per_user_limit_cb: false 68 | radius_accounting: false 69 | radius_accounting_mode: user-authentication 70 | radius_interim_accounting_interval: 0 71 | reauth_interval: 0 72 | rf_band: all 73 | roles: [] 74 | server_load_balancing: false 75 | set_role_mac_auth: '' 76 | set_role_machine_auth_machine_only: '' 77 | set_role_machine_auth_user_only: '' 78 | set_role_pre_auth: '' 79 | ssid_encoding: utf8 80 | strict_svp: false 81 | termination: false 82 | time_range_profiles_status: [] 83 | tspec: false 84 | tspec_bandwidth: 2000 85 | type: guest 86 | use_ip_for_calling_station: false 87 | user_bridging: false 88 | very_high_throughput_disable: true 89 | vlan: '' 90 | wep_index: 0 91 | wep_key: '' 92 | wispr: false 93 | wmm_background_dscp: '' 94 | wmm_background_share: 0 95 | wmm_best_effort_dscp: '' 96 | wmm_best_effort_share: 0 97 | wmm_uapsd: true 98 | wmm_video_dscp: '' 99 | wmm_video_share: 0 100 | wmm_voice_dscp: '' 101 | wmm_voice_share: 0 102 | work_without_uplink: false 103 | wpa_passphrase: 'true' 104 | zone: '' 105 | hotspot_profile: '' 106 | access_rule: 107 | name: captive-open 108 | action: allow 109 | app_rf_mv_info: '' 110 | blacklist: false 111 | classify_media: false 112 | disable_scanning: false 113 | dot1p_priority: '' 114 | eport: any 115 | ipaddr: any 116 | log: false 117 | match: match 118 | nat_ip: '' 119 | nat_port: 0 120 | netmask: any 121 | protocol: any 122 | protocol_id: '' 123 | service_name: '' 124 | service_type: network 125 | source: default 126 | sport: any 127 | throttle_downstream: '' 128 | throttle_upstream: '' 129 | time_range: '' 130 | tos: '' 131 | vlan: 0 132 | -------------------------------------------------------------------------------- /wlan_config/configurations/enterprise-network.yaml: -------------------------------------------------------------------------------- 1 | # Sample for creating enterprise security level wpa3-enterprise ccm128 network. 2 | targets: 3 | - group 4 | wlans: 5 | - wlan: 6 | access_type: network_based 7 | air_time_limit: "" 8 | air_time_limit_cb: false 9 | auth_server1: 'InternalServer' 10 | auth_server2: '' 11 | auth_survivability: false 12 | bandwidth_limit: '' 13 | bandwidth_limit_cb: false 14 | blacklist: true 15 | broadcast_filter: arp 16 | called_station_id_deli: 0 17 | called_station_id_incl_ssid: false 18 | called_station_id_type: macaddr 19 | captive_exclude: [] 20 | captive_portal: disable 21 | captive_portal_proxy_ip: '' 22 | captive_portal_proxy_port: '' 23 | captive_profile_name: 'guest_user' 24 | cloud_guest: false 25 | cluster_name: '' 26 | content_filtering: false 27 | deny_intra_vlan_traffic: false 28 | disable_ssid: false 29 | dmo_channel_util_threshold: 90 30 | dot11k: false 31 | dot11v: false 32 | download_role: false 33 | dtim_period: 1 34 | dynamic_multicast_optimization: false 35 | dynamic_vlans: [] 36 | enforce_dhcp: false 37 | essid: enterprise-test 38 | explicit_ageout_client: false 39 | g_max_tx_rate: '54' 40 | g_min_tx_rate: '1' 41 | gw_profile_name: '' 42 | hide_ssid: false 43 | high_efficiency_disable: true 44 | high_throughput_disable: true 45 | inactivity_timeout: 1000 46 | index: 1 47 | l2_auth_failthrough: false 48 | l2switch_mode: false 49 | leap_use_session_key: false 50 | local_probe_req_threshold: 0 51 | mac_authentication: false 52 | mac_authentication_delimiter: '' 53 | mac_authentication_upper_case: false 54 | management_frame_protection: false 55 | max_auth_failures: 0 56 | max_clients_threshold: 64 57 | mdid: '' 58 | multicast_rate_optimization: false 59 | name: enterprise-test 60 | okc: false 61 | oos_def: vpn-down 62 | oos_name: none 63 | oos_time: 30 64 | opmode: wpa3-aes-ccm-128 65 | opmode_transition_disable: true 66 | per_user_limit: 67 | per_user_limit_cb: false 68 | radius_accounting: false 69 | radius_accounting_mode: user-authentication 70 | radius_interim_accounting_interval: 0 71 | reauth_interval: 0 72 | rf_band: all 73 | roles: [] 74 | server_load_balancing: false 75 | set_role_mac_auth: '' 76 | set_role_machine_auth_machine_only: '' 77 | set_role_machine_auth_user_only: '' 78 | set_role_pre_auth: '' 79 | ssid_encoding: utf8 80 | strict_svp: false 81 | termination: false 82 | time_range_profiles_status: [] 83 | tspec: false 84 | tspec_bandwidth: 2000 85 | type: employee 86 | use_ip_for_calling_station: false 87 | user_bridging: false 88 | very_high_throughput_disable: true 89 | vlan: '0' 90 | wep_index: 0 91 | wep_key: '' 92 | wispr: false 93 | wmm_background_dscp: '' 94 | wmm_background_share: 0 95 | wmm_best_effort_dscp: '' 96 | wmm_best_effort_share: 0 97 | wmm_uapsd: true 98 | wmm_video_dscp: '' 99 | wmm_video_share: 0 100 | wmm_voice_dscp: '' 101 | wmm_voice_share: 0 102 | work_without_uplink: false 103 | wpa_passphrase: 'password' 104 | zone: '' 105 | hotspot_profile: '' 106 | access_rule: 107 | name: enterprise-test 108 | action: allow 109 | app_rf_mv_info: '' 110 | blacklist: false 111 | classify_media: false 112 | disable_scanning: false 113 | dot1p_priority: '' 114 | eport: any 115 | ipaddr: any 116 | log: false 117 | match: match 118 | bandwidth_limit_peruser_up: '' 119 | bandwidth_limit_peruser_down: '' 120 | bandwidth_limit_down: '' 121 | bandwidth_limit_up: '' 122 | rules: '' 123 | nat_ip: '' 124 | nat_port: 0 125 | netmask: any 126 | protocol: any 127 | protocol_id: '' 128 | service_name: '' 129 | service_type: network 130 | source: default 131 | sport: any 132 | throttle_downstream: '' 133 | throttle_upstream: '' 134 | time_range: '' 135 | tos: '' 136 | vlan: '0' 137 | -------------------------------------------------------------------------------- /wlan_config/configurations/open_network.yaml: -------------------------------------------------------------------------------- 1 | # Sample for creating a generic open network SSID. 2 | targets: 3 | - groupname 4 | wlans: 5 | - wlan: 6 | access_type: unrestricted 7 | air_time_limit: "" 8 | air_time_limit_cb: false 9 | auth_server1: '' 10 | auth_server2: '' 11 | auth_survivability: false 12 | bandwidth_limit: '' 13 | bandwidth_limit_cb: false 14 | blacklist: true 15 | broadcast_filter: arp 16 | called_station_id_deli: 0 17 | called_station_id_incl_ssid: false 18 | called_station_id_type: macaddr 19 | captive_exclude: [] 20 | captive_portal: disable 21 | captive_portal_proxy_ip: '' 22 | captive_portal_proxy_port: '' 23 | captive_profile_name: '' 24 | cloud_guest: false 25 | cluster_name: '' 26 | content_filtering: false 27 | deny_intra_vlan_traffic: false 28 | disable_ssid: false 29 | dmo_channel_util_threshold: 90 30 | dot11k: false 31 | dot11v: false 32 | download_role: false 33 | dtim_period: 1 34 | dynamic_multicast_optimization: false 35 | dynamic_vlans: [] 36 | enforce_dhcp: false 37 | essid: open-network 38 | explicit_ageout_client: false 39 | g_max_tx_rate: '54' 40 | g_min_tx_rate: '1' 41 | gw_profile_name: '' 42 | hide_ssid: false 43 | high_efficiency_disable: true 44 | high_throughput_disable: true 45 | inactivity_timeout: 1000 46 | index: 1 47 | l2_auth_failthrough: false 48 | l2switch_mode: false 49 | leap_use_session_key: false 50 | local_probe_req_threshold: 0 51 | mac_authentication: false 52 | mac_authentication_delimiter: '' 53 | mac_authentication_upper_case: false 54 | management_frame_protection: false 55 | max_auth_failures: 0 56 | max_clients_threshold: 64 57 | mdid: '' 58 | multicast_rate_optimization: false 59 | name: open-network 60 | okc: false 61 | oos_def: vpn-down 62 | oos_name: none 63 | oos_time: 30 64 | opmode: opensystem 65 | opmode_transition_disable: true 66 | per_user_limit: 67 | per_user_limit_cb: false 68 | radius_accounting: false 69 | radius_accounting_mode: user-authentication 70 | radius_interim_accounting_interval: 0 71 | reauth_interval: 0 72 | rf_band: all 73 | roles: [] 74 | server_load_balancing: false 75 | set_role_mac_auth: '' 76 | set_role_machine_auth_machine_only: '' 77 | set_role_machine_auth_user_only: '' 78 | set_role_pre_auth: '' 79 | ssid_encoding: utf8 80 | strict_svp: false 81 | termination: false 82 | time_range_profiles_status: [] 83 | tspec: false 84 | tspec_bandwidth: 2000 85 | type: guest 86 | use_ip_for_calling_station: false 87 | user_bridging: false 88 | very_high_throughput_disable: true 89 | vlan: '' 90 | wep_index: 0 91 | wep_key: '' 92 | wispr: false 93 | wmm_background_dscp: '' 94 | wmm_background_share: 0 95 | wmm_best_effort_dscp: '' 96 | wmm_best_effort_share: 0 97 | wmm_uapsd: true 98 | wmm_video_dscp: '' 99 | wmm_video_share: 0 100 | wmm_voice_dscp: '' 101 | wmm_voice_share: 0 102 | work_without_uplink: false 103 | wpa_passphrase: 'true' 104 | zone: '' 105 | hotspot_profile: '' 106 | access_rule: 107 | name: open-network 108 | action: allow 109 | app_rf_mv_info: '' 110 | blacklist: false 111 | classify_media: false 112 | disable_scanning: false 113 | dot1p_priority: '' 114 | eport: any 115 | ipaddr: any 116 | log: false 117 | match: match 118 | nat_ip: '' 119 | nat_port: 0 120 | netmask: any 121 | protocol: any 122 | protocol_id: '' 123 | service_name: '' 124 | service_type: network 125 | source: default 126 | sport: any 127 | throttle_downstream: '' 128 | throttle_upstream: '' 129 | time_range: '' 130 | tos: '' 131 | vlan: 0 -------------------------------------------------------------------------------- /wlan_config/configurations/psk_network.yaml: -------------------------------------------------------------------------------- 1 | # Sample for creating a personal security level generic wpa3 PSK network. 2 | targets: 3 | - group 4 | wlans: 5 | - wlan: 6 | access_type: unrestricted 7 | air_time_limit: "" 8 | air_time_limit_cb: false 9 | auth_server1: '' 10 | auth_server2: '' 11 | auth_survivability: false 12 | bandwidth_limit: '' 13 | bandwidth_limit_cb: false 14 | blacklist: true 15 | broadcast_filter: arp 16 | called_station_id_deli: 0 17 | called_station_id_incl_ssid: false 18 | called_station_id_type: macaddr 19 | captive_exclude: [] 20 | captive_portal: disable 21 | captive_portal_proxy_ip: '' 22 | captive_portal_proxy_port: '' 23 | captive_profile_name: '' 24 | cloud_guest: false 25 | cluster_name: '' 26 | content_filtering: false 27 | deny_intra_vlan_traffic: false 28 | disable_ssid: false 29 | dmo_channel_util_threshold: 90 30 | dot11k: false 31 | dot11v: false 32 | download_role: false 33 | dtim_period: 1 34 | dynamic_multicast_optimization: false 35 | dynamic_vlans: [] 36 | enforce_dhcp: false 37 | essid: psk-network 38 | explicit_ageout_client: false 39 | g_max_tx_rate: '54' 40 | g_min_tx_rate: '1' 41 | gw_profile_name: '' 42 | hide_ssid: false 43 | high_efficiency_disable: true 44 | high_throughput_disable: true 45 | inactivity_timeout: 1000 46 | index: 1 47 | l2_auth_failthrough: false 48 | l2switch_mode: false 49 | leap_use_session_key: false 50 | local_probe_req_threshold: 0 51 | mac_authentication: false 52 | mac_authentication_delimiter: '' 53 | mac_authentication_upper_case: false 54 | management_frame_protection: false 55 | max_auth_failures: 0 56 | max_clients_threshold: 64 57 | mdid: '' 58 | multicast_rate_optimization: false 59 | name: psk-network 60 | okc: false 61 | oos_def: vpn-down 62 | oos_name: none 63 | oos_time: 30 64 | opmode: wpa3-sae-aes 65 | opmode_transition_disable: true 66 | per_user_limit: 67 | per_user_limit_cb: false 68 | radius_accounting: false 69 | radius_accounting_mode: user-authentication 70 | radius_interim_accounting_interval: 0 71 | reauth_interval: 0 72 | rf_band: all 73 | roles: [] 74 | server_load_balancing: false 75 | set_role_mac_auth: '' 76 | set_role_machine_auth_machine_only: '' 77 | set_role_machine_auth_user_only: '' 78 | set_role_pre_auth: '' 79 | ssid_encoding: utf8 80 | strict_svp: false 81 | termination: false 82 | time_range_profiles_status: [] 83 | tspec: false 84 | tspec_bandwidth: 2000 85 | type: employee 86 | use_ip_for_calling_station: false 87 | user_bridging: false 88 | very_high_throughput_disable: true 89 | vlan: '' 90 | wep_index: 0 91 | wep_key: '' 92 | wispr: false 93 | wmm_background_dscp: '' 94 | wmm_background_share: 0 95 | wmm_best_effort_dscp: '' 96 | wmm_best_effort_share: 0 97 | wmm_uapsd: true 98 | wmm_video_dscp: '' 99 | wmm_video_share: 0 100 | wmm_voice_dscp: '' 101 | wmm_voice_share: 0 102 | work_without_uplink: false 103 | wpa_passphrase: 'password' 104 | zone: '' 105 | hotspot_profile: '' 106 | access_rule: 107 | name: psk-network 108 | action: allow 109 | app_rf_mv_info: '' 110 | blacklist: false 111 | classify_media: false 112 | disable_scanning: false 113 | dot1p_priority: '' 114 | eport: any 115 | ipaddr: any 116 | log: false 117 | match: match 118 | nat_ip: '' 119 | nat_port: 0 120 | netmask: any 121 | protocol: any 122 | protocol_id: '' 123 | service_name: '' 124 | service_type: network 125 | source: default 126 | sport: any 127 | throttle_downstream: '' 128 | throttle_upstream: '' 129 | time_range: '' 130 | tos: '' 131 | vlan: 0 -------------------------------------------------------------------------------- /wlan_config/create_ssid_workflow.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | 5 | """ 6 | Workflow creates a new SSID for target group or device. This includes creation 7 | of an ArubaCentralBase instance through the usage of a config file, which is 8 | required for pycentral API usage. SSID details should be pre-configured in a 9 | YAML file to be used by the workflow. Please refer to the README for full 10 | configuration file details. The workflow will create a new SSID configured to 11 | the YAML files settings. 12 | """ 13 | 14 | from pycentral.workflows.workflows_utils import get_conn_from_file 15 | from wlan import WlanConfig 16 | from argparse import ArgumentParser 17 | import yaml 18 | import json 19 | import os 20 | import sys 21 | 22 | 23 | def main(): 24 | 25 | args = define_arguments() 26 | 27 | # Create ArubaCentralBase Instance. 28 | central = get_conn_from_file(args.central_auth) 29 | 30 | # Open and load wlan data. 31 | file_info = open(args.config_path) 32 | ssid_info = yaml.safe_load(file_info) 33 | 34 | wlan = WlanConfig() 35 | 36 | if "targets" not in ssid_info: 37 | sys.exit("Bad YAML structure, missing 'targets' key in file." 38 | " Exiting...") 39 | # Iterate through each target and WLAN config. 40 | for target in ssid_info["targets"]: 41 | if "wlans" not in ssid_info: 42 | sys.exit("Bad YAML structure, missing 'wlans' key in file." 43 | " Exiting...") 44 | for ssid in ssid_info["wlans"]: 45 | if "wlan" not in ssid: 46 | sys.exit("Bad substructure for WLANs list. Check key values." 47 | " Exiting...") 48 | # Check format for proper API to use. 49 | if 'opmode' not in ssid["wlan"]: 50 | # Create SSID. 51 | wlan.create_ssid(conn=central, target=target, 52 | wlan_data=ssid) 53 | else: 54 | # Format data for API. 55 | json_str = json.dumps(ssid) 56 | data = {"value": json_str} 57 | # Create SSID. 58 | wlan.create_full_ssid(conn=central, target=target, 59 | name=ssid["wlan"]["essid"], 60 | wlan_data=data) 61 | 62 | file_info.close() 63 | 64 | 65 | def define_arguments(): 66 | """ 67 | This function defines command line arguments that can be used with this 68 | workflow. 69 | 70 | :return: Argparse namespace with central auth filepath and ssid config 71 | filepath. 72 | :type return: argparse.Namespace 73 | """ 74 | 75 | description = "This workflow creates SSIDs in target Central group, guid,"\ 76 | " or serial. SSID configuration is provided via json file." 77 | 78 | parser = ArgumentParser(description=description) 79 | parser.add_argument('--central_auth', help=('Central Credential auth' 80 | ' filepath'), 81 | default='central_token.yaml') 82 | parser.add_argument('--config_path', help=('SSID configuration filepath'), 83 | required=True, type=validate_path) 84 | 85 | return parser.parse_args() 86 | 87 | 88 | def validate_path(path): 89 | """ 90 | Validates input for config_path CLI argument. 91 | 92 | :param path: file path for ssid configuration. 93 | :return: path 94 | """ 95 | 96 | if not os.path.exists(path): 97 | sys.exit("Invalid file path for config_path argument. Exiting...") 98 | 99 | return path 100 | 101 | 102 | if __name__ == "__main__": 103 | main() 104 | -------------------------------------------------------------------------------- /wlan_config/delete_ssid_workflow.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | 5 | """ 6 | Workflow deletes all SSIDs listed in user provided json file for target 7 | group/GUID/serial. This workflow requires creation of an ArubaCentralBase 8 | instance through the usage of a config file, which is required for 9 | pycentral API usage. Target SSID group name and SSID name should be 10 | pre-configured in a json file to be used by the workflow. Full details 11 | on structure can be found in the associated readme. 12 | """ 13 | 14 | from pycentral.workflows.workflows_utils import get_conn_from_file 15 | from wlan import WlanConfig 16 | from argparse import ArgumentParser 17 | import yaml 18 | import sys 19 | import os 20 | 21 | 22 | def main(): 23 | 24 | args = define_arguments() 25 | 26 | # Create ArubaCentralBase Instance. 27 | central = get_conn_from_file(filename=args.central_auth) 28 | 29 | # Setup YAML data. 30 | file_info = open(args.config_path) 31 | ssid_info = yaml.safe_load(file_info) 32 | 33 | SSIDWorkflow = WlanConfig() 34 | 35 | for target in ssid_info["targets"]: 36 | if args.a: 37 | SSIDWorkflow.delete_all(central, target) 38 | else: 39 | for ssid in ssid_info["delete_list"]: 40 | SSIDWorkflow.delete_ssid(central, target, ssid) 41 | 42 | file_info.close() 43 | 44 | 45 | def define_arguments(): 46 | """ 47 | This function defines command line arguments that can be used with this 48 | workflow. 49 | 50 | :return: Argparse namespace with central auth filepath and ssid config 51 | filepath. 52 | :type return: argparse.Namespace 53 | """ 54 | 55 | description = "This workflow deletes SSIDs in target Central group, guid,"\ 56 | " or serial. SSID configuration is provided via YAML file." 57 | 58 | # Add arguments. 59 | parser = ArgumentParser(description=description) 60 | parser.add_argument('-a', help=('Delete all SSIDs in UI group'), 61 | action='store_true') 62 | parser.add_argument('--central_auth', help=('Central Credential auth' 63 | ' filepath'), 64 | default='central_token.yaml') 65 | parser.add_argument('--config_path', help=('Delete config YAML filepath'), 66 | required=True, type=validate_path) 67 | 68 | return parser.parse_args() 69 | 70 | 71 | def validate_path(path): 72 | """ 73 | Validates input for config_path CLI argument. 74 | 75 | :param path: file path for ssid configuration. 76 | :return: path 77 | """ 78 | 79 | if not os.path.exists(path): 80 | sys.exit("Invalid file path for config_path argument. Exiting...") 81 | 82 | return path 83 | 84 | 85 | if __name__ == "__main__": 86 | main() 87 | -------------------------------------------------------------------------------- /wlan_config/requirements.txt: -------------------------------------------------------------------------------- 1 | certifi==2024.7.4 2 | charset-normalizer==3.3.2 3 | idna==3.7 4 | pycentral==1.4.1 5 | PyYAML==6.0.1 6 | requests==2.32.2 7 | urllib3==2.2.2 8 | -------------------------------------------------------------------------------- /wlan_config/wlan.py: -------------------------------------------------------------------------------- 1 | # MIT License 2 | # 3 | # Copyright (c) 2023 Aruba, a Hewlett Packard Enterprise company 4 | # 5 | # Permission is hereby granted, free of charge, to any person obtaining a copy 6 | # of this software and associated documentation files (the "Software"), to deal 7 | # in the Software without restriction, including without limitation the rights 8 | # to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | # copies of the Software, and to permit persons to whom the Software is 10 | # furnished to do so, subject to the following conditions: 11 | # 12 | # The above copyright notice and this permission notice shall be included in 13 | # all copies or substantial portions of the Software. 14 | # 15 | # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | # IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | # FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | # AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | # LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | # OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | # SOFTWARE. 22 | 23 | from pycentral.configuration import Wlan 24 | import sys 25 | 26 | 27 | class WlanConfig(object): 28 | """ 29 | Contains functions to manage Aruba Central WLANs. 30 | """ 31 | 32 | def create_ssid(self, conn, target, wlan_data): 33 | """ 34 | Create new ssid at target. 35 | 36 | :param conn: Instance of class:`pycentral.ArubaCentralBase` to make an 37 | API call. 38 | :type conn: class:`pycentral.ArubaCentralBase` 39 | :param wlan_data: SSID config data. 40 | :type wlan_data: json 41 | """ 42 | 43 | if target == "": 44 | sys.exit("Invalid value for 'target'. Please add a valid target" 45 | " and run again.") 46 | 47 | resp = Wlan.create_wlan(self, conn, group_name=target, 48 | wlan_name=wlan_data["wlan"]["essid"], 49 | wlan_data=wlan_data) 50 | 51 | if resp["code"] != 200: 52 | print("Bad request for create_wlan() SSID: %s at target: %s," 53 | " response code: %d. %s" % 54 | (wlan_data["wlan"]["essid"], target, resp["code"], 55 | resp["msg"]["description"])) 56 | else: 57 | print("Successfully created SSID: %s at %s" % 58 | (wlan_data["wlan"]["essid"], target)) 59 | 60 | def create_full_ssid(self, conn, target, name, wlan_data): 61 | """ 62 | Create new fully configurable ssid at target. 63 | 64 | :param conn: Instance of class:`pycentral.ArubaCentralBase` to make an 65 | API call. 66 | :type conn: class:`pycentral.ArubaCentralBase` 67 | :param wlan_data: SSID config data. 68 | :type wlan_data: json 69 | """ 70 | 71 | if target == "": 72 | sys.exit("Invalid value for 'target'. Please add a valid target" 73 | " and run again.") 74 | 75 | resp = Wlan.create_full_wlan(self, conn, group_name=target, 76 | wlan_name=name, 77 | wlan_data=wlan_data) 78 | 79 | if resp["code"] != 200: 80 | print("Bad request for create_full_wlan() SSID: %s at target: %s," 81 | " response code: %d. %s" % (name, target, resp["code"], 82 | resp["msg"]["description"])) 83 | else: 84 | print("Successfully created SSID: %s at %s" % 85 | (name, target)) 86 | 87 | def delete_ssid(self, conn, target, ssid): 88 | """ 89 | Delete ssid at target provided in wlan_data. 90 | 91 | :param conn: Instance of class:`pycentral.ArubaCentralBase` to make an 92 | API call. 93 | :type conn: class:`pycentral.ArubaCentralBase` 94 | :param wlan_data: SSID config data. 95 | :type wlan_data: json 96 | """ 97 | 98 | if target == "": 99 | sys.exit("Invalid value for 'target'. Please add a valid target" 100 | " and run again.") 101 | 102 | resp = Wlan.delete_wlan(self, conn, target, ssid) 103 | 104 | if resp["code"] != 200: 105 | print( 106 | "Bad request for delete_wlan() response code: %d. " 107 | "%s" % (resp["code"], resp["msg"]["description"])) 108 | else: 109 | print("Successfully deleted SSID: %s at %s" % 110 | (ssid, target)) 111 | 112 | def delete_all(self, conn, target): 113 | """ 114 | Delete all SSIDs at target Central group. 115 | 116 | :param conn: Instance of class:`pycentral.ArubaCentralBase` to make an 117 | API call. 118 | :type conn: class:`pycentral.ArubaCentralBase` 119 | :param target: Cerntral group name 120 | :type target: str 121 | """ 122 | 123 | # Get all SSIDs from target Central group. 124 | ssid_res = Wlan.get_all_wlans(self, conn, target) 125 | if ssid_res["code"] != 200: 126 | print( 127 | "Bad request for get_all_wlans() response code: %d. " 128 | "%s" % (ssid_res["code"], ssid_res["msg"]["description"])) 129 | else: 130 | print("Successfully retrieved SSIDs from %s" % 131 | (target)) 132 | 133 | # Set SSID data. 134 | ssid_list = ssid_res["msg"]["wlans"] 135 | 136 | # Delete all SSIDs in ssid_list. 137 | for ssid in ssid_list: 138 | resp = Wlan.delete_wlan(self, conn, target, ssid["essid"]) 139 | if resp["code"] != 200: 140 | print( 141 | "Bad request for delete_wlan() response code: %d. " 142 | "%s" % (resp["code"], resp["msg"]["description"])) 143 | else: 144 | print("Successfully deleted SSID: %s at %s" % 145 | (ssid, target)) 146 | 147 | def get_config(self, conn, target, name): 148 | """ 149 | Gets full configuration of a WLAN in a Central group. 150 | 151 | :param conn: Instance of class:`pycentral.ArubaCentralBase` to make an 152 | API call. 153 | :type conn: class:`pycentral.ArubaCentralBase` 154 | :param group_name: Group name of the group or guid of the swarm. 155 | :type group_name: str 156 | :param wlan_name: Name string for wlan to get. 157 | :type wlan_name: str 158 | 159 | :return: Encoded JSON string of WLAN data. 160 | :rtype: str 161 | """ 162 | 163 | resp = Wlan.get_wlan(self, conn, target, name) 164 | 165 | if resp["code"] != 200: 166 | print( 167 | "Bad request for get_wlan() response code: %d. " 168 | "%s" % (resp["code"], resp["msg"]["description"])) 169 | 170 | return resp 171 | --------------------------------------------------------------------------------