### Example PCG Mapping Configuration Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Provides a concrete example of the PCG_Mapping dictionary. This maps specific XIQ group IDs to user group names and PCG policy details. ```python PCG_Mapping = { "group-eng-123": { "UserGroupName": "Engineers", "policy_id": "policy-001", "policy_name": "Engineer Network Access Policy" }, "group-sales-456": { "UserGroupName": "Sales", "policy_id": "policy-002", "policy_name": "Sales Network Access Policy" } } ``` -------------------------------- ### Install Dependencies Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Installs the required Python packages for the script using pip. Ensure you have Python 3.6+ installed. ```bash pip install -r requirements.txt ``` -------------------------------- ### Create a New PPSK User Object Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example of creating a dictionary representing a new PPSK user with required fields for ExtremeCloudIQ. ```python new_user = { "user_group_id": "group-123", "name": "John Doe", "user_name": "john.doe", "password": "", "email_address": "john.doe@company.com", "email_password_delivery": "john.doe@company.com" } ``` -------------------------------- ### Show First 50 Lines of Script Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Display the first 50 lines of the script to quickly review its content or starting sections. ```bash head -50 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Error Counter Summary Example Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/5-errors.md Provides an example of the summary output for error counters at the end of a script run, indicating the number of failed operations for PPSK and PCG user creation and deletion. ```text There were 2 errors creating PPSK users on this run. There were 0 errors creating PCG users on this run. There were 1 errors deleting PPSK users on this run. There were 0 errors deleting PCG users on this run. ``` -------------------------------- ### Configure Group Role Mapping Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example configuration of the group_roles list, which maps Active Directory groups to XIQ user groups. This setup is crucial for assigning appropriate roles to users synchronized from AD. ```python group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-eng-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-sales-456"), ("CN=Managers,CN=Users,DC=company,DC=local", "group-mgr-789") ] ``` -------------------------------- ### Log Format Example Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Illustrates the standard log entry format: TIMESTAMP LEVEL MESSAGE. ```text TIMESTAMP LEVEL MESSAGE 2025-05-16 14:30:45: root - INFO - Message here ``` -------------------------------- ### Usage Example for PCG Mapping Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Demonstrates how to use the PCG_Mapping dictionary to retrieve policy information based on an XIQ role. Ensure PCG is enabled and the XIQ role exists in the mapping. ```python if PCG_Enable == True and str(details['xiq_role']) in PCG_Mapping: policy_id = PCG_Mapping[details['xiq_role']]['policy_id'] policy_name = PCG_Mapping[details['xiq_role']]['policy_name'] user_group_name = PCG_Mapping[details['xiq_role']]['UserGroupName'] result = addUserToPcg(policy_id, name, email, user_group_name) ``` -------------------------------- ### Check Installed Dependencies Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md List installed Python packages and filter for essential libraries like requests, ldap3, and pycryptodome. ```bash pip list | grep -E requests\|ldap3\|pycryptodome ``` -------------------------------- ### Check Python Version Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Verify that Python 3.6 or later is installed on the system. ```bash python3 --version ``` -------------------------------- ### Configure Windows Task Scheduler for XIQ AD Sync Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Set up a scheduled task in Windows to run the XIQ-AD-PPSK-Sync.py script. Specify the Python executable, script arguments, and the starting directory. ```powershell 1. Open Task Scheduler 2. Create Basic Task 3. Set Trigger: Daily or Hourly 4. Set Action: - Program: `C:\Python\python.exe` - Arguments: `C:\path\XIQ-AD-PPSK-Sync.py` - Start in: `C:\path` ``` -------------------------------- ### Add PCG User Payload Example Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example of the payload structure for adding a user to a PCG policy. This dictionary format is used as a request payload. ```python user_to_add = { "name": "john.doe", "email": "john.doe@company.com", "user_group_name": "Engineers" } ``` -------------------------------- ### Usage Example for Login Response Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Shows how to extract the access token from the login response and format it for subsequent API requests. The token type is typically 'Bearer'. ```python data = response.json() if "access_token" in data: headers["Authorization"] = "Bearer " + data["access_token"] ``` -------------------------------- ### Useful Log Entries Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Examples of common log entries for successful operations, failed operations, warnings, and summary statistics. ```text # Successful operations successfully created PPSK user john.doe User john.doe - was successfully deleted. # Failed operations failed to create john.doe: HTTP Status Code: 400 Error adding PPSK user john.doe - HTTP Status Code: 400 # Warnings User john.doe doesn't have an email set User john.doe is is disabled in AD with disable code 514 # Summary Successfully parsed 42 XIQ users Successfully parsed 45 LDAP users There were 2 errors creating PPSK users on this run. ``` -------------------------------- ### Create LDAP User Dictionary Entry Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example of creating an entry in the ldap_users dictionary during the AD user retrieval phase. It populates the dictionary with user details fetched from Active Directory. ```python ldap_users[str(ldap_entry.name)] = { "userAccountControl": str(ldap_entry.userAccountControl), "email": str(ldap_entry.mail), "username": str(ldap_entry.sAMAccountName), "xiq_role": "group-123" } ``` -------------------------------- ### Apply Group Role Mapping to Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example demonstrating how to use the group_roles mapping to assign XIQ roles to users based on their Active Directory group membership. It iterates through the mappings and updates user dictionaries. ```python ListOfADgroups, ListOfXIQUserGroups = zip(*group_roles) # ListOfADgroups = ( # "CN=Engineers,CN=Users,DC=company,DC=local", # "CN=Sales,CN=Users,DC=company,DC=local", # ... # ) # ListOfXIQUserGroups = ("group-eng-123", "group-sales-456", ...) for ad_group, xiq_user_role in group_roles: ad_result = retrieveADUsers(ad_group) for ldap_entry in ad_result: ldap_users[str(ldap_entry.name)]["xiq_role"] = xiq_user_role ``` -------------------------------- ### GET /endusers Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md Retrieves all PPSK users with pagination support. Can filter by user group. ```APIDOC ## GET /endusers ### Description Retrieves all PPSK users with pagination support. Can filter by user group. ### Method GET ### Endpoint /endusers?page={page}&limit={limit}&user_group_ids={usergroupID} #### Query Parameters - **page** (integer) - Yes - Page number (1-indexed) - **limit** (integer) - Yes - Number of results per page (max 100) - **user_group_ids** (string) - Yes - XIQ user group ID to filter by ### Response #### Success Response (200 OK) - **page** (integer) - Current page number - **limit** (integer) - Results per page - **total_pages** (integer) - Total number of pages available - **total_count** (integer) - Total number of users matching filter - **data** (array) - Array of user objects - **data[].id** (string) - Unique user ID in XIQ - **data[].user_name** (string) - Username (typically matches AD name) - **data[].name** (string) - User display name - **data[].email_address** (string) - User email address - **data[].user_group_id** (string) - XIQ user group ID - **data[].email_password_delivery** (string) - Email for password delivery #### Response Example ```json { "page": 1, "limit": 100, "total_pages": 1, "total_count": 42, "data": [ { "id": "user-123", "user_name": "john.doe", "name": "John Doe", "email_address": "john.doe@company.com", "user_group_id": "group-456", "email_password_delivery": "john.doe@company.com" } ] } ``` ``` -------------------------------- ### LDAP Filtering for AD Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Use these Python examples to construct LDAP filters for excluding computer accounts, selecting only enabled users, filtering by specific departments, or combining multiple conditions. ```python # Exclude computer accounts AD_Filter = "(&(!(objectCategory=computer)))" ``` ```python # Only enabled users AD_Filter = "(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" ``` ```python # Specific departments AD_Filter = "(department=Engineering)" ``` ```python # Combine multiple conditions AD_Filter = "(&(department=Engineering)(!(userAccountControl:1.2.840.113556.1.4.803:=2))))" ``` -------------------------------- ### Python Error Logging Patterns Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/5-errors.md Illustrates various scenarios for logging errors, warnings, and informational messages using Python's logging module. Includes examples for API failures, missing user data, LDAP extraction issues, and disabled accounts. ```python logging.error(f"Error adding PPSK user {name} - HTTP Status Code: {response.status_code}") logging.warning(f"\t\t{response.json()}") ``` ```python logging.warning(log_msg) ``` ```python logging.error(log_msg) logging.warning("User info was not captured from Active Directory") ``` ```python logging.info(f"User {name} is is disabled in AD with disable code ...") ``` -------------------------------- ### Get Authentication Token Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Obtain an access token for ExtremeCloudIQ by providing username and password. Alternatively, the token can be set directly via configuration. ```python # Get token from username/password getAccessToken("user@company.com", "password") # Token is set via configuration: XIQ_token = "eyJ..." ``` -------------------------------- ### Retrieve PPSK Users with Filtering Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md Use this endpoint to get a paginated list of PPSK users. You can filter results by user group ID. Ensure you include the 'Accept' and 'Authorization' headers. ```python url = "https://api.extremecloudiq.com/endusers?page=1&limit=100&user_group_ids=group-123" headers = {"Accept": "application/json", "Authorization": "Bearer " + token} response = requests.get(url, headers=headers) users = response.json()["data"] total_pages = response.json()["total_pages"] ``` -------------------------------- ### Xiq-AD-PPSK-Sync Algorithm Steps Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Outlines the sequential steps involved in the synchronization process between Active Directory and Xiq. ```text 1. Authenticate to XIQ 2. Retrieve existing PPSK users 3. Retrieve AD users from all groups 4. For each AD user NOT in XIQ: └─ Create user in XIQ └─ Add to PCG if enabled 5. For each XIQ user NOT in AD: └─ Remove from PCG if enabled └─ Delete from XIQ 6. Report error counts ``` -------------------------------- ### Manually Run XIQ AD User Sync Script Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Execute the XIQ-AD-PPSK-Sync.py script directly from the command line to sync AD users with XIQ. ```bash cd /path/to/XIQ-AD-User-Sync python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Minimal Configuration (Python) Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/3-configuration.md Use this minimal configuration when PCG integration is not required. It sets up basic connection details and group role mappings. ```python server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_service" password = "ServicePassword123" XIQ_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." group_roles = [ ("CN=Users,DC=company,DC=local", "user-group-001") ] PCG_Enable = False ``` -------------------------------- ### Running the XIQ-AD-PPSK-Sync Script Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Execute the script with different options for standard operation, debugging, or scheduling on Linux and Windows systems. ```bash # Standard run python3 XIQ-AD-PPSK-Sync.py ``` ```bash # Debug mode LOGLEVEL=DEBUG python3 XIQ-AD-PPSK-Sync.py ``` ```bash # Scheduled (Linux cron) 5 * * * * cd /opt/xiq-sync && python3 XIQ-AD-PPSK-Sync.py ``` ```bash # Scheduled (Windows Task Scheduler) Program: C:\Python\python.exe Arguments: C:\Scripts\XIQ-AD-PPSK-Sync.py Start in: C:\Scripts ``` -------------------------------- ### Clone Repository Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Clones the XIQ AD User Sync repository from GitHub and navigates into the project directory. ```bash git clone https://github.com/ExtremeNetworksSA/XIQ-AD-User-Sync.git cd XIQ-AD-User-Sync ``` -------------------------------- ### Configure Script Variables Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Sets up essential configuration parameters within the Python script, including Active Directory and ExtremeCloudIQ credentials, and group mappings. ```python # Active Directory Configuration server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_service" password = "SecurePassword123" # ExtremeCloudIQ Configuration XIQ_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." # Group Mappings group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-eng-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-sales-456") ] # PCG Configuration (optional) PCG_Enable = False ``` -------------------------------- ### Get AD group Distinguished Name (DN) Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Retrieve the Distinguished Name (DN) of an Active Directory group using PowerShell. ```powershell # Windows PowerShell Get-ADGroup -Identity "Engineers" | Select-Object DistinguishedName # Output: CN=Engineers,CN=Users,DC=company,DC=local ``` -------------------------------- ### Run XIQ AD User Sync Script Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Executes the main synchronization script. Monitor the console output and the generated log file for detailed information about the sync process. ```bash python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Required Configuration Variables Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/9-project-overview.md Define essential Active Directory and ExtremeCloudIQ credentials and mappings. Ensure these variables are correctly set before running the script. ```python # Active Directory server_name = "ad.company.local" # AD server hostname/IP domain_name = "company.local" # AD domain user_name = "sync_service" # AD service account password = "password123" # AD service account password # ExtremeCloudIQ XIQ_token = "eyJhbGc..." # API token # Mappings group_roles = [ # AD group -> XIQ group mapping ("CN=Eng,CN=Users,DC=...", "group-123"), ("CN=Sales,CN=Users,DC=...", "group-456") ] ``` -------------------------------- ### main Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/2-api-reference-ad-functions.md Tests AD connectivity and displays user details in a readable format. It resolves the server hostname, performs a reverse DNS lookup, retrieves users, and prints their details. ```APIDOC ## main ### Description Tests AD connectivity and displays user details in a readable format. It resolves the server hostname, performs a reverse DNS lookup, retrieves users, and prints their details. ### Signature ```python def main() -> None ``` ### Behavior 1. Resolves server hostname to IP address (if not already an IP) 2. Performs reverse DNS lookup on resolved IP 3. Retrieves users from configured distinguished name 4. Prints each user's details: name, userAccountControl, email, sAMAccountName ### Example Usage ```bash python3 AD_Test.py ``` ### Output Example ``` The ip address for ad.company.local is 192.168.1.100 engineers { 'userAccountControl': '512', 'email': 'engineers@company.local', 'username': 'engineers_group' } ``` ``` -------------------------------- ### Parse PCG Users List Response Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example code for parsing the JSON response from a PCG users list endpoint. Accumulates user data and updates pagination variables. ```python rawList = response.json() PCGUsers = PCGUsers + rawList['data'] pageCount = rawList['total_pages'] page = rawList['page'] + 1 ``` -------------------------------- ### Schedule XIQ AD User Sync with Debug Logging Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Configure the crontab entry to run the XIQ-AD-PPSK-Sync.py script with DEBUG level logging enabled for more detailed output. ```bash 5 * * * * LOGLEVEL=DEBUG cd /path/to/XIQ-AD-User-Sync && python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Optional Configuration Variables Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/9-project-overview.md Configure optional settings for PCG integration, LDAP query parameters, and XIQ API pagination. These settings can be adjusted based on specific environment needs. ```python # PCG Integration PCG_Enable = True # Enable PCG sync PCG_Mapping = {...} # XIQ group -> PCG policy mapping # LDAP page = 1000 # LDAP page size AD_Filter = "" # Additional LDAP filter # API pageSize = 100 # XIQ API page size (max 100) ``` -------------------------------- ### Complete Configuration with PCG (Python) Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/3-configuration.md This configuration includes all options for integrating with Policy Controller Gateway (PCG). It specifies PCG mapping for XIQ groups to policies and enables PCG integration. ```python server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_service" password = "ServicePassword123" page = 1000 AD_Filter = "(&(!(objectCategory=computer))) " # Exclude computers XIQ_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." pageSize = 100 group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-eng-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-sales-456") ] PCG_Enable = True PCG_Mapping = { "group-eng-123": { "UserGroupName": "Engineers", "policy_id": "pcg-policy-001", "policy_name": "Engineer Access Policy" }, "group-sales-456": { "UserGroupName": "Sales", "policy_id": "pcg-policy-002", "policy_name": "Sales Access Policy" } } ``` -------------------------------- ### Create Missing PPSK Users Logic Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md Iterates through AD users, checks for email presence, existence in XIQ, and AD disabled status before attempting to create a new PPSK user. Logs warnings for missing emails and errors during creation. ```python for name, details in ldap_users.items(): user_created = False # Check for missing email if details['email'] == '[]': logging.warning(f"User {name} doesn't have an email...") continue # Check if user exists in XIQ or is disabled if not any(d['user_name'] == name for d in ppsk_users) \ and not any(d == details['userAccountControl'] for d in ldap_disable_codes): try: user_created = createPPSKuser(name, details["email"], details['xiq_role']) except TypeError as e: logging.error(f"failed to create {name}: {e}") ppsk_create_error += 1 ``` -------------------------------- ### main Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/1-api-reference-xiq-functions.md The primary entry point for the user synchronization process. It orchestrates the synchronization of Active Directory users to ExtremeCloudIQ, including PPSK and PCG users, handling creation, updates, and deletions. ```APIDOC ## main ### Description Primary entry point that orchestrates the synchronization of Active Directory users to ExtremeCloudIQ PPSK and PCG users. It handles user creation, addition to PCG policies, deletion, and removal from PCG policies. ### Method Not specified (Python function) ### Endpoint Not specified (Python function) ### Parameters None. Uses global variables for configuration: #### Global Variables - **Xiq_username** (str) - Optional - XIQ username (if token not provided) - **Xiq_password** (str) - Optional - XIQ password (if token not provided) - **Xiq_token** (str) - Optional - XIQ API token (alternative to username/password) - **group_roles** (list[tuple]) - Yes - List of tuples: (AD group DN, XIQ user group ID) - **PCG_Enable** (bool) - No - Enable PCG synchronization (Default: False) - **PCG_Mapping** (dict) - No - Mapping of XIQ group IDs to PCG policies (Default: {}) - **server_name** (str) - Yes - Active Directory server name or IP - **domain_name** (str) - Yes - Active Directory domain name - **user_name** (str) - Yes - Active Directory username for authentication - **password** (str) - Yes - Active Directory password - **AD_Filter** (str) - No - LDAP filter to further restrict AD user search (Default: "") - **pageSize** (int) - No - XIQ API page size (max 100) (Default: 100) ### Request Example ```python # Configuration (set global variables before calling) server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_service" password = "SecurePassword123" XIQ_token = "eyJhbGciOiJIUzI1NiIs..." group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-456") ] PCG_Enable = False # Run synchronization main() ``` ### Response `None` — Logs results and errors to file and prints status to console. ### Behavior 1. Authenticates to XIQ using token or username/password 2. Retrieves PPSK users from all configured XIQ groups 3. Retrieves Active Directory users from all configured AD groups 4. Creates new users in XIQ that exist in AD but not in XIQ 5. Adds newly created users to PCG policies if PCG is enabled 6. Deletes users from XIQ that exist in XIQ but not in AD 7. Removes deleted users from PCG policies if PCG is enabled 8. Logs error counts for create and delete operations ``` -------------------------------- ### Parse PPSK Users List Response Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Example code for parsing the JSON response from a PPSK users list endpoint. Appends new data to an existing list and updates page count. ```python rawList = response.json() ppskUsers = ppskUsers + rawList['data'] pageCount = rawList['total_pages'] page = rawList['page'] + 1 ``` -------------------------------- ### Get Access Token for XIQ API Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/1-api-reference-xiq-functions.md Authenticates with ExtremeCloudIQ API using username and password. Updates global headers with the Authorization Bearer token upon success. Handles TypeErrors for authentication failures. ```python try: getAccessToken("username@company.com", "password123") # headers now contains Authorization Bearer token except TypeError as e: print(f"Authentication failed: {e}") sys.exit(1) ``` -------------------------------- ### Run Script with Environment Variables Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Execute the Python script while providing environment variables for AD_PASSWORD and XIQ_TOKEN directly on the command line. Ensure sensitive values are quoted. ```bash XIQ_TOKEN="token..." AD_PASSWORD="pass..." python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Schedule XIQ AD User Sync Script with Crontab Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Automate the XIQ-AD-PPSK-Sync.py script to run hourly using crontab on Linux/macOS systems. Logs are redirected to a specified file. ```bash # Edit crontab crontab -e # Add entry (runs at 5 minutes past each hour) 5 * * * * cd /path/to/XIQ-AD-User-Sync && python3 XIQ-AD-PPSK-Sync.py >> /var/log/xiq-sync.log 2>&1 ``` -------------------------------- ### Xiq AD User Sync Data Flow Diagram Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/9-project-overview.md Illustrates the data flow for user synchronization, from Active Directory queries to ExtremeCloudIQ user and PCG policy management. ```text Active Directory ──(LDAP queries)──> XIQ AD User Sync │ [Comparison Logic] │ ┌────────┴────────┐ │ │ Create Users Delete Users │ │ ExtremeCloudIQ PPSK <──(Create API calls)──X──(Delete API calls) │ │ └────────┬────────┘ │ Add to/Remove from PCG │ ExtremeCloudIQ PCG ``` -------------------------------- ### Enable PCG Integration Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Set this Python variable to True to enable Provisioning Cloud Gateway integration. ```python PCG_Enable = True ``` -------------------------------- ### Active Directory and ExtremeCloudIQ Configuration Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Configuration settings for connecting to Active Directory and ExtremeCloudIQ, including group mappings and optional PCG settings. Ensure all required parameters are provided. ```python # REQUIRED: Active Directory server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_account" password = "MyPassword123" # REQUIRED: ExtremeCloudIQ XIQ_token = "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9..." # REQUIRED: Group Mappings group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-456") ] # OPTIONAL: PCG PCG_Enable = True PCG_Mapping = { "group-123": { "UserGroupName": "Engineers", "policy_id": "pcg-policy-001", "policy_name": "Engineer Network" } } ``` -------------------------------- ### Converting LDAP Entry Fields to Strings Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Demonstrates converting various LDAP entry fields to strings for consistent handling in XIQ. Note that the 'email' field might be represented as '[]' if missing. ```python # LDAP entry fields "userAccountControl": str(ldap_entry.userAccountControl), # int -> str "email": str(ldap_entry.mail), # [array] -> str "username": str(ldap_entry.sAMAccountName), # str -> str # XIQ IDs can be int or str policy_id: str | int # Both accepted in URLs ``` -------------------------------- ### Adjusting Page Sizes for Performance Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Configure AD and XIQ page sizes to optimize data retrieval performance. The default AD page size is 1000, while XIQ has a maximum of 100. ```python # AD page size (default 1000) page = 500 ``` ```python # XIQ page size (max 100, default 100) pageSize = 50 ``` -------------------------------- ### createPPSKuser Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/1-api-reference-xiq-functions.md Creates a new PPSK (Pre-Shared Key) user in ExtremeCloudIQ. Returns `True` on successful user creation. ```APIDOC ## createPPSKuser ### Description Creates a new PPSK (Pre-Shared Key) user in ExtremeCloudIQ. ### Signature ```python def createPPSKuser(name: str, mail: str, usergroupID: str) -> bool ``` ### Parameters #### Path Parameters - name (str) - Required - User name to create in XIQ - mail (str) - Required - Email address for password delivery - usergroupID (str) - Required - XIQ user group ID to assign user to ### Return Type `bool` - Returns `True` on successful user creation. ### Throws - TypeError: No response from server or HTTP status code is not 200 ### Example ```python try: success = createPPSKuser("john.doe", "john@company.com", "group-123") if success: print("User created successfully") except TypeError as e: print(f"Failed to create user: {e}") ``` ``` -------------------------------- ### POST /endusers Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md Creates a new PPSK user in ExtremeCloudIQ. ```APIDOC ## POST /endusers ### Description Creates a new PPSK user in ExtremeCloudIQ. ### Method POST ### Endpoint /endusers #### Request Body - **user_group_id** (string) - Yes - XIQ user group ID to assign user to - **name** (string) - Yes - User display name - **user_name** (string) - Yes - Username for login - **password** (string) - Yes - User password (empty string for auto-generated) - **email_address** (string) - Yes - User email address - **email_password_delivery** (string) - Yes - Email to send password delivery notification ### Request Example ```json { "user_group_id": "group-123", "name": "John Doe", "user_name": "john.doe", "password": "", "email_address": "john.doe@company.com", "email_password_delivery": "john.doe@company.com" } ``` ### Response #### Success Response (200 OK) - **id** (string) - Unique user ID in XIQ - **user_name** (string) - Username (typically matches AD name) - **name** (string) - User display name - **email_address** (string) - User email address - **user_group_id** (string) - XIQ user group ID #### Response Example ```json { "id": "user-789", "user_name": "john.doe", "name": "John Doe", "email_address": "john.doe@company.com", "user_group_id": "group-456" } ``` ``` -------------------------------- ### Configure Python Logging Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/3-configuration.md Set up logging for the script, directing output to a file and formatting messages with timestamps, logger name, level, and the message content. The logging level is dynamically set from the LOGLEVEL environment variable, defaulting to INFO. ```python logging.basicConfig( filename='{}/XIQ-AD-PPSK-sync.log'.format(PATH), filemode='a', level=os.environ.get("LOGLEVEL", "INFO"), format='%(asctime)s: %(name)s - %(levelname)s - %(message)s', datefmt='%Y-%m-%d %H:%M:%S' ) ``` -------------------------------- ### Create PPSK User in XIQ Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/1-api-reference-xiq-functions.md Creates a new PPSK user in ExtremeCloudIQ with the specified name, email, and user group ID. Returns True on success and handles TypeErrors for API communication failures. ```python try: success = createPPSKuser("john.doe", "john@company.com", "group-123") if success: print("User created successfully") except TypeError as e: print(f"Failed to create user: {e}") ``` -------------------------------- ### Load XIQ Token and AD Password from Environment Variables Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Load sensitive credentials like XIQ API tokens and Active Directory passwords from environment variables to avoid hardcoding them in scripts. Ensure the environment variables are set before running the script. ```python import os XIQ_token = os.environ.get("XIQ_TOKEN") password = os.environ.get("AD_PASSWORD") ``` -------------------------------- ### Xiq AD User Sync Architecture Diagram Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/9-project-overview.md Visual representation of the Xiq AD User Sync project's component structure, showing the interaction between authentication, data retrieval, sync logic, and logging. ```text XIQ AD User Sync ├── Authentication Layer │ ├── XIQ API token/username/password │ └── AD service account credentials ├── Data Retrieval │ ├── Active Directory LDAP queries │ └── ExtremeCloudIQ API calls ├── Sync Logic │ ├── User comparison algorithm │ ├── Create operations │ ├── Delete operations │ └── PCG integration └── Logging └── File-based operation log ``` -------------------------------- ### Determine Authentication Method in Python Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md This snippet checks for an existing XIQ token and uses it if available. Otherwise, it attempts to log in using provided username and password. ```python if 'XIQ_token' not in globals(): login = getAccessToken(XIQ_username, XIQ_password) else: headers["Authorization"] = "Bearer " + XIQ_token ``` -------------------------------- ### Environment Variables for Logging and Script Execution Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Set the logging level for the script or execute the main synchronization script. ```bash # Set logging level export LOGLEVEL=DEBUG export LOGLEVEL=INFO export LOGLEVEL=ERROR # Run script python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Handle PPSK User Creation Errors Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/5-errors.md Use a try-except block to catch TypeErrors during PPSK user creation, logging the error and incrementing an error counter. ```python try: user_created = createPPSKuser(name, details["email"], details['xiq_role']) except TypeError as e: log_msg = f"failed to create {name}: {e}" logging.error(log_msg) print(log_msg) ppsk_create_error += 1 ``` -------------------------------- ### Retrieve and Print PPSK User Details Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Demonstrates retrieving a list of PPSK users and iterating through them to print their ID, username, and email address. This snippet is typically returned by `retrievePPSKUsers()`. ```python ppsk_users = retrievePPSKUsers("group-123") for user in ppsk_users: print(f"ID: {user['id']}") print(f"Username: {user['user_name']}") print(f"Email: {user['email_address']}") ``` -------------------------------- ### Add New Users to PCG Policies Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md Conditionally adds newly created users to PCG policies if PCG is enabled, the user was created, and their XIQ role is mapped to a PCG policy. Handles potential TypeErrors during the addition process. ```python if PCG_Enable == True and user_created == True \ and str(details['xiq_role']) in PCG_Mapping: policy_id = PCG_Mapping[details['xiq_role']]['policy_id'] policy_name = PCG_Mapping[details['xiq_role']]['policy_name'] user_group_name = PCG_Mapping[details['xiq_role']]['UserGroupName'] email = details["email"] try: result = addUserToPcg(policy_id, name, email, user_group_name) if result == 'Success': logging.info(f"User {name} - was successfully add to pcg {policy_name}.") except TypeError as e: logging.error(f"failed to add {name} to pcg {policy_name}: {e}") pcg_create_error += 1 ``` -------------------------------- ### Orchestrate User Synchronization Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/1-api-reference-xiq-functions.md The main function to synchronize Active Directory users with ExtremeCloudIQ PPSK and PCG users. Ensure all global configuration variables are set before calling. ```python # Configuration (set global variables before calling) server_name = "ad.company.local" domain_name = "company.local" user_name = "sync_service" password = "SecurePassword123" XIQ_token = "eyJhbGciOiJIUzI1NiIs..." group_roles = [ ("CN=Engineers,CN=Users,DC=company,DC=local", "group-123"), ("CN=Sales,CN=Users,DC=company,DC=local", "group-456") ] PCG_Enable = False # Run synchronization main() ``` -------------------------------- ### Set Log Level for XIQ AD Sync Script Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Control the verbosity of the XIQ-AD-PPSK-Sync.py script's output by setting the LOGLEVEL environment variable to DEBUG, INFO, or ERROR. ```bash LOGLEVEL=DEBUG python3 XIQ-AD-PPSK-Sync.py LOGLEVEL=INFO python3 XIQ-AD-PPSK-Sync.py LOGLEVEL=ERROR python3 XIQ-AD-PPSK-Sync.py ``` -------------------------------- ### Test XIQ API Connectivity Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Use curl to test connectivity to the XIQ API, fetching a list of end-users. ```bash curl -H "Authorization: Bearer $XIQ_TOKEN" \ https://api.extremecloudiq.com/endusers?page=1&limit=1 ``` -------------------------------- ### Check XIQ API Reachability Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Use curl to test if the XIQ API endpoint is reachable, including the necessary authentication header. ```bash curl https://api.extremecloudiq.com/endusers ``` -------------------------------- ### Iterate Through LDAP User Dictionary Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Demonstrates how to iterate through the ldap_users dictionary to access details for each synchronized user. This is used to determine user creation, deletion, and group assignments in XIQ. ```python for name, details in ldap_users.items(): print(f"User: {name}") print(f" Email: {details['email']}") print(f" Role: {details['xiq_role']}") print(f" Account Status: {details['userAccountControl']}") ``` -------------------------------- ### API Endpoints for User Management Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md These endpoints are used to authenticate, list, create, and delete PPSK and PCG users. ```bash POST /login # Authenticate GET /endusers # List PPSK users POST /endusers # Create PPSK user DELETE /endusers/{userId} # Delete PPSK user GET /pcgs/key-based/network-policy-{id}/users # List PCG users POST /pcgs/key-based/network-policy-{id}/users # Add to PCG DELETE /pcgs/key-based/network-policy-{id}/users # Remove from PCG ``` -------------------------------- ### PCG Mapping Configuration Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/3-configuration.md Configure Provisioning Cloud Gateway (PCG) synchronization by mapping XIQ user group IDs to specific network policies. This enables automated policy assignment based on user group membership. ```python PCG_Enable = True PCG_Mapping = { "group-engineers-123": { "UserGroupName": "Engineers", "policy_id": "policy-001", "policy_name": "Engineer Network Policy" }, "group-sales-456": { "UserGroupName": "Sales", "policy_id": "policy-002", "policy_name": "Sales Network Policy" } } ``` -------------------------------- ### POST /login - Authenticate with ExtremeCloudIQ Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md Authenticates with ExtremeCloudIQ using username and password to obtain an access token. Ensure the request body is in JSON format and includes the correct Content-Type header. ```python url = "https://api.extremecloudiq.com/login" payload = json.dumps({"username": "user@company.com", "password": "pass123"}) response = requests.post(url, headers=headers, data=payload) if response.status_code == 200: token = response.json()["access_token"] ``` -------------------------------- ### POST /login Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md Authenticates with ExtremeCloudIQ using username and password to obtain an access token. ```APIDOC ## POST /login ### Description Authenticates with ExtremeCloudIQ using username and password to obtain an access token. ### Method POST ### Endpoint /login ### Parameters #### Request Body - **username** (string) - Required - ExtremeCloudIQ username - **password** (string) - Required - ExtremeCloudIQ password ### Request Example ```json { "username": "string", "password": "string" } ``` ### Response #### Success Response (200 OK) - **access_token** (string) - JWT token for subsequent API calls - **token_type** (string) - Token type (always "Bearer") - **expires_in** (integer) - Token expiration time in seconds #### Response Example ```json { "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...", "token_type": "Bearer", "expires_in": 3600 } ``` ``` -------------------------------- ### Handle Missing User Email Errors Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/5-errors.md Check if the 'email' attribute for a user is empty or '[]' before attempting to create the user in XIQ. Logs a warning and skips the user if the email is missing. ```python if details['email'] == '[]': log_msg = (f"User {name} doesn't have an email set and will not be created in xiq") logging.warning(log_msg) print(log_msg) continue ``` -------------------------------- ### Test XIQ API Access with Curl Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Verify that you can access the XIQ API by making a test request using curl. This helps diagnose authentication and authorization issues. ```bash curl -H "Authorization: Bearer $TOKEN" https://api.extremecloudiq.com/endusers?page=1&limit=1 ``` -------------------------------- ### Handle SystemExit for Fatal AD Connection Errors Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/5-errors.md This snippet demonstrates how to catch SystemExit exceptions, which indicate fatal errors preventing script continuation, such as failures in connecting to Active Directory. The script prints an error message and terminates. ```python try: ad_users = retrieveADUsers("CN=Users,DC=company,DC=local") except SystemExit: print("Fatal error: could not retrieve Active Directory users") # Script terminates ``` -------------------------------- ### Count Successfully Created Users in Log Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Count the number of lines in the log file that indicate a user was successfully created. This helps in tracking the script's success rate. ```bash grep "successfully created PPSK user" XIQ-AD-PPSK-sync.log | wc -l ``` -------------------------------- ### Monitor Log File in Real-Time Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/10-quick-reference.md Continuously monitor the specified log file for new entries as they are written. This is useful for observing script activity in real-time. ```bash tail -f XIQ-AD-PPSK-sync.log ``` -------------------------------- ### Map XIQ Groups to PCG Policies Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/8-integration-guide.md Configure a Python dictionary to map ExtremeCloudIQ user group IDs to specific Provisioning Cloud Gateway policies, including user group name and policy details. ```python PCG_Mapping = { "group-eng-123": { "UserGroupName": "Engineers", "policy_id": "policy-001", "policy_name": "Engineer Network Access" }, "group-sales-456": { "UserGroupName": "Sales", "policy_id": "policy-002", "policy_name": "Sales Network Access" } } ``` -------------------------------- ### Retrieve and Print PCG Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/6-data-types.md Demonstrates how to retrieve a list of PCG users for a given policy and iterate through them to print their details. Requires the `retrievePCGUsers` function. ```python pcg_users = retrievePCGUsers("policy-001") for user in pcg_users: print(f"PCG ID: {user['id']}") print(f"Email: {user['email']}") ``` -------------------------------- ### Test AD Connectivity and Retrieve Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/2-api-reference-ad-functions.md A utility script to test Active Directory connectivity and retrieve user details. It resolves server hostnames, performs reverse DNS lookups, and displays user information in a readable format. Run this script to validate AD configuration before using the main synchronization script. ```bash python3 AD_Test.py ``` -------------------------------- ### Retrieve XIQ PPSK Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md Iterates through XIQ user group IDs to retrieve all PPSK users. Handles pagination automatically and exits if retrieval fails. ```python ppsk_users = [] for usergroupID in ListOfXIQUserGroups: try: ppsk_users += retrievePPSKUsers(usergroupID) except TypeError as e: print(e) raise SystemExit except: raise SystemExit ``` -------------------------------- ### Check for User Creation in XIQ Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md Determines if a user exists in LDAP but not in XIQ, indicating a need for user creation. Assumes 'name' is the user identifier. ```python if not any(d['user_name'] == name for d in ppsk_users): # Create user ``` -------------------------------- ### Create a New PPSK User Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/4-endpoints.md This endpoint allows for the creation of a new PPSK user. Provide all required user details in the JSON request body. An empty string for 'password' will result in an auto-generated password. ```python url = "https://api.extremecloudiq.com/endusers" payload = json.dumps({ "user_group_id": "group-123", "name": "John Doe", "user_name": "john.doe", "password": "", "email_address": "john.doe@company.com", "email_password_delivery": "john.doe@company.com" }) headers = {"Content-Type": "application/json", "Authorization": "Bearer " + token} response = requests.post(url, headers=headers, data=payload) ``` -------------------------------- ### Retrieve Active Directory Users Source: https://github.com/extremenetworkssa/xiq-ad-user-sync/blob/master/_autodocs/7-workflow-sync-algorithm.md Fetches users from configured AD groups and maps them to XIQ roles. Logs duplicate user entries and handles LDAP query failures. ```python ldap_users = {} for ad_group, xiq_user_role in group_roles: ad_result = retrieveADUsers(ad_group) for ldap_entry in ad_result: if str(ldap_entry.name) not in ldap_users: ldap_users[str(ldap_entry.name)] = { "userAccountControl": str(ldap_entry.userAccountControl), "email": str(ldap_entry.mail), "username": str(ldap_entry.sAMAccountName), "xiq_role": xiq_user_role } else: logging.error(f"User {ldap_entry.name} has multiple entries...") ```