Skip to content

Instantly share code, notes, and snippets.

@RichardDally
Created May 21, 2025 22:09
Show Gist options
  • Save RichardDally/d2b44b6f371a59c2ff7e27b5a06d2806 to your computer and use it in GitHub Desktop.
Save RichardDally/d2b44b6f371a59c2ff7e27b5a06d2806 to your computer and use it in GitHub Desktop.
Generate Artifactory token
import requests
import json
import logging
import os
# --- Logger Setup ---
logging.basicConfig(
level=logging.INFO,
format='%(asctime)s - %(levelname)s - %(message)s',
handlers=[
logging.StreamHandler() # Log to console
# You could add logging.FileHandler("token_generation.log") here to log to a file
]
)
logger = logging.getLogger(__name__)
# --- Configuration ---
# These should ideally be set via environment variables or a secure config file
ARTIFACTORY_URL = os.getenv("ARTIFACTORY_URL", "https://YOUR_ARTIFACTORY_URL")
LDAP_USERNAME = os.getenv("ARTIFACTORY_LDAP_USERNAME", "your_ldap_username")
LDAP_PASSWORD = os.getenv("ARTIFACTORY_LDAP_PASSWORD", "your_ldap_password")
# Token details (optional, adjust as needed in your environment or configuration)
TOKEN_SCOPE = os.getenv("ARTIFACTORY_TOKEN_SCOPE", "api:*")
_expires_in_str = os.getenv("ARTIFACTORY_TOKEN_EXPIRES_IN_SECONDS")
TOKEN_EXPIRES_IN_SECONDS = int(_expires_in_str) if _expires_in_str and _expires_in_str.isdigit() else 3600
_refreshable_str = os.getenv("ARTIFACTORY_TOKEN_REFRESHABLE", "True")
TOKEN_REFRESHABLE = _refreshable_str.lower() == 'true'
TOKEN_AUDIENCE = os.getenv("ARTIFACTORY_TOKEN_AUDIENCE") # e.g., "*@*" or specific service IDs
TOKEN_DESCRIPTION = os.getenv("ARTIFACTORY_TOKEN_DESCRIPTION", "Python generated token")
# --- API Endpoint ---
TOKEN_ENDPOINT = f"{ARTIFACTORY_URL.rstrip('/')}/artifactory/api/security/token"
def generate_token():
"""
Generates an Artifactory access token using LDAP credentials.
"""
# --- Request Payload ---
payload = {
"username": LDAP_USERNAME, # Can be omitted if authenticating user is the token subject
"scope": TOKEN_SCOPE,
}
# Add optional parameters to the payload if they have been set
if TOKEN_EXPIRES_IN_SECONDS is not None: # 0 is a valid value for non-expiring (subject to global limits)
payload["expires_in"] = TOKEN_EXPIRES_IN_SECONDS
if TOKEN_REFRESHABLE is not None:
payload["refreshable"] = TOKEN_REFRESHABLE
if TOKEN_AUDIENCE:
payload["audience"] = TOKEN_AUDIENCE
if TOKEN_DESCRIPTION:
payload["description"] = TOKEN_DESCRIPTION
# --- Sensitive Data Check ---
if "YOUR_ARTIFACTORY_URL" in ARTIFACTORY_URL or \
"your_ldap_username" == LDAP_USERNAME or \
"your_ldap_password" == LDAP_PASSWORD:
logger.warning("Default placeholder values detected for URL or credentials. "
"Please configure them properly via environment variables or directly in the script.")
# return None # Optionally exit if not configured
logger.info(f"Attempting to generate token for user '{LDAP_USERNAME}' at '{TOKEN_ENDPOINT}'")
logger.debug(f"Request payload (excluding sensitive data if username is same as auth user): { {k:v for k,v in payload.items() if k != 'username' or payload.get('username') != LDAP_USERNAME} }")
try:
response = requests.post(
TOKEN_ENDPOINT,
auth=(LDAP_USERNAME, LDAP_PASSWORD), # Basic Authentication with LDAP credentials
json=payload # Send data as JSON
)
response.raise_for_status() # Raise an exception for bad status codes (4xx or 5xx)
token_data = response.json()
logger.info("--- Token Generated Successfully! ---")
# Avoid logging the full token directly to INFO unless necessary for debugging in controlled env
logger.debug(f"Full token data: {token_data}")
logger.info(f"Access Token: [REDACTED - see DEBUG log for full token if enabled]") # Or just log a portion token_data.get('access_token', '')[:10] + "..."
logger.info(f"Token Type: {token_data.get('token_type')}")
if "expires_in" in token_data:
logger.info(f"Expires In (seconds): {token_data.get('expires_in')}")
if "scope" in token_data:
logger.info(f"Scope: {token_data.get('scope')}")
if "refresh_token" in token_data:
logger.info(f"Refresh Token: [REDACTED - see DEBUG log for full token if enabled]")
return token_data
except requests.exceptions.HTTPError as errh:
logger.error("--- HTTP Error ---")
logger.error(f"Error: {errh}")
logger.error(f"Response Status Code: {errh.response.status_code}")
try:
error_details = errh.response.json()
logger.error(f"Response Body: {json.dumps(error_details, indent=2)}")
except json.JSONDecodeError:
logger.error(f"Response Body: {errh.response.text}")
except requests.exceptions.ConnectionError as errc:
logger.error("--- Error Connecting ---")
logger.error(f"Error: {errc}. Check ARTIFACTORY_URL and network connectivity.")
except requests.exceptions.Timeout as errt:
logger.error("--- Timeout Error ---")
logger.error(f"Error: {errt}")
except requests.exceptions.RequestException as err:
logger.error("--- Request Exception ---")
logger.error(f"Error: {err}")
except Exception as e:
logger.error("--- An unexpected error occurred ---")
logger.error(f"Error: {e}", exc_info=True) # exc_info=True will log stack trace
return None
if __name__ == "__main__":
generated_token_info = generate_token()
if generated_token_info:
# The token details are already logged by the function.
# You might want to use/store generated_token_info.get('access_token') here.
# For security, avoid printing the raw token to stdout in production scripts.
logger.info("Token generation process finished.")
# Example: print(f"Access Token: {generated_token_info.get('access_token')}") # If needed for piping
else:
logger.error("Token generation failed. Check logs for details.")
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment