Last active
September 18, 2023 11:17
-
-
Save merlos/e2157b644f9b956093d439c352bddcd1 to your computer and use it in GitHub Desktop.
Python script to get all the AD groups from Graph API
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import requests | |
import csv | |
import msal | |
import os | |
""" | |
Script to save into a file csv file the name of the groups of Active Directory | |
It requires 3 environment variables | |
CLIENT_ID | |
SECRET_ID | |
TENANT_ID | |
CLIENT_ID and SECRET_ID are obtained from creating an App Registration | |
https://learn.microsoft.com/en-us/azure/active-directory/develop/scenario-daemon-app-registration | |
MSAL (Microsoft Authentication Library) needs to be installed | |
pip install msal | |
""" | |
# Load the variables from environment variables | |
client_id = os.environ.get("CLIENT_ID") | |
client_secret = os.environ.get("CLIENT_SECRET") | |
tenant_id = os.environ.get("TENANT_ID") | |
# Check if any of the variables is not set or is empty | |
if not client_id or not client_secret or not tenant_id: | |
print("Error: The following environment variables are required and must be set:") | |
if not client_id: | |
print(" - CLIENT_ID") | |
if not client_secret: | |
print(" - CLIENT_SECRET") | |
if not tenant_id: | |
print(" - TENANT_ID") | |
print("\nTo set these variables, you can use the following commands in your terminal:") | |
print("export CLIENT_ID=YourClientId") | |
print("export CLIENT_SECRET=YourClientSecret") | |
print("export TENANT_ID=YourTenantId") | |
else: | |
# Variables are set, you can proceed with your code | |
print("Environment variables loaded successfully:") | |
scope = ["https://graph.microsoft.com/.default"] | |
# Create a preferably long-lived app instance that maintains a token cache. | |
app = msal.ConfidentialClientApplication( | |
client_id, | |
authority=f"https://login.microsoftonline.com/{tenant_id}", | |
client_credential=client_secret | |
# token_cache=... # Default cache is in memory only. | |
# You can learn how to use SerializableTokenCache from | |
# https://msal-python.rtfd.io/en/latest/#msal.SerializableTokenCache | |
) | |
result = None | |
# We now check the cache to see | |
# whether we already have some accounts that the end user already used to sign in before. | |
accounts = app.get_accounts() | |
if accounts: | |
# If so, you could then somehow display these accounts and let end user choose | |
print("Pick the account you want to use to proceed:") | |
for a in accounts: | |
print(a["username"]) | |
# Assuming the end user chose this one | |
chosen = accounts[0] | |
# Now let's try to find a token in cache for this account | |
result = app.acquire_token_silent(scope, account=chosen) | |
else: | |
# First, the code looks up a token from the cache. | |
# Because we're looking for a token for the current app, not for a user, | |
# use None for the account parameter. | |
result = app.acquire_token_silent(scope, account=None) | |
if not result: | |
print("No suitable token exists in cache. Let's get a new one from Azure AD.") | |
result = app.acquire_token_for_client(scopes=scope) | |
if "access_token" in result: | |
# Call a protected API with the access token. | |
print("Token type" + result["token_type"]) | |
else: | |
print(result.get("error")) | |
print(result.get("error_description")) | |
print(result.get("correlation_id")) # You might need this when reporting a bug. | |
# Create a headers dictionary with the access token | |
headers = { | |
"Authorization": "Bearer " + result["access_token"] | |
} | |
# Create a list to store all the groups | |
all_groups = [] | |
current_page = 1 | |
# Define your initial URL | |
graph_url = "https://graph.microsoft.com/v1.0/groups?$select=displayName" | |
while graph_url: | |
# Make a GET request with the headers including the access token | |
response = requests.get(graph_url, headers=headers) | |
# Check if the request was successful | |
if response.status_code == 200: | |
print (f"Received response 200 for page {current_page}") | |
groups_data = response.json() | |
groups = groups_data.get("value", []) | |
print(groups_data) | |
all_groups.extend(groups) | |
print (f" all_groups length={len(all_groups)}") | |
# Check if there's a next link for more pages | |
next_link = groups_data.get("@odata.nextLink") | |
print (f" next_link={next_link}") | |
if next_link: | |
graph_url = next_link | |
current_page= current_page+1 | |
else: | |
# No more pages, exit the loop | |
graph_url = None | |
else: | |
print(f"Failed to retrieve groups. Status code: {response.status_code}") | |
print(response.text) | |
break | |
# Save all_groups to a CSV file | |
csv_file_path = "groups.csv" | |
with open(csv_file_path, mode="w", newline="", encoding="utf-8") as csv_file: | |
csv_writer = csv.writer(csv_file) | |
csv_writer.writerow(["Group Name"]) | |
for group in all_groups: | |
csv_writer.writerow([group["displayName"]]) | |
print(f"Groups have been saved to {csv_file_path}") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment