From 1e69ced5da3a5e3ee5d1c81d3edb37d195627232 Mon Sep 17 00:00:00 2001 From: not-lucky Date: Sun, 17 Aug 2025 14:01:12 +0530 Subject: [PATCH] emails.txt --- .gitignore | 11 +++- README.md | 43 +++++++++++++++ main.py | 139 ++++++++++++++++++++++++++++++++--------------- requirements.txt | 4 ++ 4 files changed, 151 insertions(+), 46 deletions(-) create mode 100644 requirements.txt diff --git a/.gitignore b/.gitignore index 575444d..37a0c5b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,12 @@ +# Virtual Environment +.venv/ + +# Python cache +__pycache__/ +*.pyc + +# Credentials and Secrets credentials/ +credentials.json *.key -*.json \ No newline at end of file +emails.txt \ No newline at end of file diff --git a/README.md b/README.md index e69de29..a3cad54 100644 --- a/README.md +++ b/README.md @@ -0,0 +1,43 @@ +# Gemini Key Management + +This script automates the process of creating Google Cloud API keys for the Generative Language API (Gemini) across multiple Google Cloud projects. + +## Prerequisites + +- Python 3.12 or higher +- A Google Cloud account and project + +## Setup + +1. **Create OAuth Client ID credentials:** + - Go to the [Google Cloud Console](https://console.cloud.google.com/apis/credentials). + - Click on **Create Credentials** and select **OAuth client ID**. + - Select **Desktop app** as the application type. + - Give it a name and click **Create**. + - Download the JSON file and save it as `credentials.json` in the root of this project. + +2. **Install dependencies:** + ```bash + pip install -r requirements.txt + ``` + *(Note: A `requirements.txt` file will be generated in a later step)* + +3. **Create `emails.txt` file:** + - Create a file named `emails.txt` in the root of the project. + - Add the email addresses of the Google accounts you want to process, one email per line. + +## Usage + +Run the script from your terminal: + +```bash +python main.py +``` + +The first time you run the script for a new email address, you will be prompted to authenticate with your Google account in your web browser. A token file will be saved in the `credentials` directory for future runs. + +The script will then: +- Find all Google Cloud projects accessible by the authenticated user. +- Enable the `generativelanguage.googleapis.com` API for each project. +- Create a new API key named "Gemini API Key" with restrictions to the Generative Language API. +- Save the API key to a file named `.key`. diff --git a/main.py b/main.py index 020d6a2..1446dd9 100644 --- a/main.py +++ b/main.py @@ -1,82 +1,104 @@ import os +import sys import google.auth from google.oauth2.credentials import Credentials from google_auth_oauthlib.flow import InstalledAppFlow from google.cloud import resourcemanager_v3, service_usage_v1, api_keys_v2 from google.api_core import exceptions as google_exceptions -from google.oauth2 import id_token from google.auth.transport import requests # --- CONFIGURATION --- -EMAILS = [ - "aetheriumglimmer" -] CREDENTIALS_DIR = "credentials" +EMAILS_FILE = "emails.txt" +CLIENT_SECRETS_FILE = "credentials.json" # --------------------- SCOPES = [ "https://www.googleapis.com/auth/cloud-platform", - "https://www.googleapis.com/auth/userinfo.email", - "openid" ] +def load_emails_from_file(filename): + """Loads a list of emails from a text file.""" + if not os.path.exists(filename): + print(f"Error: Email file not found at '{filename}'") + print("Please create it and add one email address per line.") + return [] + with open(filename, "r") as f: + return [line.strip() for line in f if line.strip()] + def main(): + """Main function to orchestrate API key creation.""" + if not os.path.exists(CLIENT_SECRETS_FILE): + print(f"Error: OAuth client secrets file not found at '{CLIENT_SECRETS_FILE}'") + print("Please follow the setup instructions in README.md to create it.") + sys.exit(1) + if not os.path.exists(CREDENTIALS_DIR): os.makedirs(CREDENTIALS_DIR) - for email in EMAILS: + emails = load_emails_from_file(EMAILS_FILE) + if not emails: + sys.exit(1) + + for email in emails: print(f"--- Processing account: {email} ---") creds = get_credentials_for_email(email) if not creds: + print(f"Could not get credentials for {email}. Skipping.") continue try: resource_manager = resourcemanager_v3.ProjectsClient(credentials=creds) - projects = resource_manager.search_projects() + projects = list(resource_manager.search_projects()) # Convert iterator to list - print("Processing projects...") + if not projects: + print(f"No projects found for {email}.") + continue + + print(f"Found {len(projects)} projects. Processing...") for project in projects: project_id = project.project_id - print(f"- {project_id}") - enable_api(project_id, creds) - key = create_api_key(project_id, creds) - if key: - save_api_key(email, key.key_string) + print(f"- Project: {project_id}") + if enable_api(project_id, creds): + key = create_api_key(project_id, creds) + if key: + save_api_key(email, project_id, key.key_string) + except google_exceptions.PermissionDenied as err: + print(f"Permission denied for account {email}. Check IAM roles.") + print(f" Error: {err}") except google_exceptions.GoogleAPICallError as err: - print(f"An error occurred while processing account {email}: {err}") + print(f"An API error occurred while processing account {email}: {err}") def get_credentials_for_email(email): + """Handles the OAuth2 flow for a given email.""" token_file = os.path.join(CREDENTIALS_DIR, f"{email}.json") creds = None - if os.path.exists(token_file): - creds = Credentials.from_authorized_user_file(token_file, SCOPES) - - if not creds or not creds.valid: - if creds and creds.expired and creds.refresh_token: - creds.refresh(google.auth.transport.requests.Request()) - else: - print(f"Please authenticate with: {email}") - flow = InstalledAppFlow.from_client_secrets_file( - "credentials.json", SCOPES - ) - creds = flow.run_local_server(port=0) - with open(token_file, "w") as token: - token.write(creds.to_json()) - return creds - -def get_user_email(credentials): try: - request = requests.Request() - id_info = id_token.verify_oauth2_token( - credentials.id_token, request, clock_skew_in_seconds=3 - ) - return id_info["email"] - except ValueError as err: - print(f"Error getting user email: {err}") + if os.path.exists(token_file): + creds = Credentials.from_authorized_user_file(token_file, SCOPES) + + if not creds or not creds.valid: + if creds and creds.expired and creds.refresh_token: + print("Refreshing credentials...") + creds.refresh(google.auth.transport.requests.Request()) + else: + print(f"Please authenticate with: {email}") + flow = InstalledAppFlow.from_client_secrets_file( + CLIENT_SECRETS_FILE, SCOPES + ) + # Use login_hint to pre-fill the email address + creds = flow.run_local_server(port=0, login_hint=email) + with open(token_file, "w") as token: + token.write(creds.to_json()) + return creds + except Exception as e: + print(f"An unexpected error occurred during authentication: {e}") return None + def enable_api(project_id, credentials): + """Enables the Generative Language API for a project.""" try: service_usage_client = service_usage_v1.ServiceUsageClient(credentials=credentials) service_name = "generativelanguage.googleapis.com" @@ -84,32 +106,59 @@ def enable_api(project_id, credentials): name=f"projects/{project_id}/services/{service_name}" ) operation = service_usage_client.enable_service(request=request) + print("Waiting for API enablement to complete...") operation.result() # Wait for the operation to complete print(f"Enabled Generative Language API for project {project_id}") + return True + except google_exceptions.PermissionDenied as err: + print(f"Permission denied to enable API for project {project_id}. Skipping.") + return False except google_exceptions.GoogleAPICallError as err: + # Check if the error is that the API is already enabled + if "already been enabled" in str(err): + print(f"Generative Language API is already enabled for project {project_id}") + return True print(f"Error enabling API for project {project_id}: {err}") + return False def create_api_key(project_id, credentials): + """Creates a new, restricted API key.""" try: api_keys_client = api_keys_v2.ApiKeysClient(credentials=credentials) + + # Define the API target for restrictions + api_target = api_keys_v2.ApiTarget(service="generativelanguage.googleapis.com") + + # Define the key with restrictions key = api_keys_v2.Key( - display_name="Gemini API Key" + display_name="Gemini API Key", + restrictions=api_keys_v2.Restrictions( + api_targets=[api_target] + ), ) + request = api_keys_v2.CreateKeyRequest( parent=f"projects/{project_id}/locations/global", key=key, ) + print("Creating API key...") operation = api_keys_client.create_key(request=request) result = operation.result() # Wait for the operation to complete - print(f"Created API key for project {project_id}") + print(f"Successfully created restricted API key for project {project_id}") return result + except google_exceptions.PermissionDenied as err: + print(f"Permission denied to create API key for project {project_id}. Skipping.") + return None except google_exceptions.GoogleAPICallError as err: print(f"Error creating API key for project {project_id}: {err}") return None -def save_api_key(email, api_key): - with open(f"{email}.key", "a") as f: - f.write(f"{api_key}\n") +def save_api_key(email, project_id, api_key): + """Saves the API key to a file, including the project ID.""" + filename = f"{email}.keys.txt" + with open(filename, "a") as f: + f.write(f"Project: {project_id}\nKey: {api_key}\n\n") + print(f"Saved API key to {filename}") if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/requirements.txt b/requirements.txt new file mode 100644 index 0000000..8d41c08 --- /dev/null +++ b/requirements.txt @@ -0,0 +1,4 @@ +google-auth-oauthlib>=1.2.2 +google-cloud-api-keys>=0.5.17 +google-cloud-resource-manager>=1.14.2 +google-cloud-service-usage>=1.13.1