allow deletion of keys

This commit is contained in:
2025-08-18 11:55:01 +05:30
parent be0aac52ee
commit 0721e8f960
2 changed files with 105 additions and 35 deletions

View File

@@ -1,6 +1,6 @@
# Gemini Key Management # 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. This script automates the process of creating and deleting Google Cloud API keys for the Generative Language API (Gemini) across multiple Google Cloud projects.
## Prerequisites ## Prerequisites
@@ -20,19 +20,26 @@ This script automates the process of creating Google Cloud API keys for the Gene
```bash ```bash
pip install -r requirements.txt pip install -r requirements.txt
``` ```
*(Note: A `requirements.txt` file will be generated in a later step)*
3. **Create `emails.txt` file:** 3. **Create `emails.txt` file (for creating keys in bulk):**
- Create a file named `emails.txt` in the root of the project. - 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. - Add the email addresses of the Google accounts you want to process, one email per line. You can add comments with `#`.
## Usage ## Usage
Run the script from your terminal: Run the script from your terminal with a specified action (`create` or `delete`).
```bash ### Creating API Keys
python main.py
``` - **For all users in `emails.txt`:**
```bash
python main.py create
```
- **For a single user:**
```bash
python main.py create --email your.email@example.com
```
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 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.
@@ -40,4 +47,14 @@ The script will then:
- Find all Google Cloud projects accessible by the authenticated user. - Find all Google Cloud projects accessible by the authenticated user.
- Enable the `generativelanguage.googleapis.com` API for each project. - 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. - Create a new API key named "Gemini API Key" with restrictions to the Generative Language API.
- Save the API key to a file named `<email>.key`. - Save the API key(s) to a file named `<email>.keys.txt`.
### Deleting API Keys
To delete all API keys with the display name "Gemini API Key" for a specific user, run:
```bash
python main.py delete --email your.email@example.com
```
This will iterate through all projects accessible by that user and remove the matching keys.

103
main.py
View File

@@ -1,5 +1,6 @@
import os import os
import sys import sys
import argparse
import google.auth import google.auth
from google.oauth2.credentials import Credentials from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow from google_auth_oauthlib.flow import InstalledAppFlow
@@ -18,16 +19,22 @@ SCOPES = [
] ]
def load_emails_from_file(filename): def load_emails_from_file(filename):
"""Loads a list of emails from a text file.""" """Loads a list of emails from a text file, ignoring comments."""
if not os.path.exists(filename): if not os.path.exists(filename):
print(f"Error: Email file not found at '{filename}'") print(f"Error: Email file not found at '{filename}'")
print("Please create it and add one email address per line.") print("Please create it and add one email address per line.")
return [] return []
with open(filename, "r") as f: with open(filename, "r") as f:
# Ignore empty lines and lines starting with #
return [line.strip() for line in f if line.strip() and not line.startswith("#")] return [line.strip() for line in f if line.strip() and not line.startswith("#")]
def main(): def main():
"""Main function to orchestrate API key creation.""" """Main function to orchestrate API key creation or deletion."""
parser = argparse.ArgumentParser(description="Manage Gemini API keys in Google Cloud projects.")
parser.add_argument("action", choices=['create', 'delete'], help="The action to perform: 'create' or 'delete' API keys.")
parser.add_argument("--email", help="Specify a single email address to process. Required for 'delete' action. If not provided for 'create', emails will be read from emails.txt.")
args = parser.parse_args()
if not os.path.exists(CLIENT_SECRETS_FILE): if not os.path.exists(CLIENT_SECRETS_FILE):
print(f"Error: OAuth client secrets file not found at '{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.") print("Please follow the setup instructions in README.md to create it.")
@@ -36,39 +43,56 @@ def main():
if not os.path.exists(CREDENTIALS_DIR): if not os.path.exists(CREDENTIALS_DIR):
os.makedirs(CREDENTIALS_DIR) os.makedirs(CREDENTIALS_DIR)
emails = load_emails_from_file(EMAILS_FILE) emails_to_process = []
if not emails: if args.email:
emails_to_process.append(args.email)
elif args.action == 'delete':
print("Error: The 'delete' action requires the --email argument.")
sys.exit(1) sys.exit(1)
else: # action is 'create' and no email provided
emails_to_process = load_emails_from_file(EMAILS_FILE)
if not emails_to_process:
print("No emails found in emails.txt. Exiting.")
sys.exit(1)
for email in emails: for email in emails_to_process:
print(f"--- Processing account: {email} ---") process_account(email, args.action)
creds = get_credentials_for_email(email)
if not creds:
print(f"Could not get credentials for {email}. Skipping.")
continue
try: def process_account(email, action):
resource_manager = resourcemanager_v3.ProjectsClient(credentials=creds) """Processes a single account for the given action."""
projects = list(resource_manager.search_projects()) # Convert iterator to list print(f"--- Processing account: {email} for action: {action} ---")
creds = get_credentials_for_email(email)
if not creds:
print(f"Could not get credentials for {email}. Skipping.")
return
if not projects: try:
print(f"No projects found for {email}.") resource_manager = resourcemanager_v3.ProjectsClient(credentials=creds)
continue projects = list(resource_manager.search_projects())
print(f"Found {len(projects)} projects. Processing...") if not projects:
for project in projects: print(f"No projects found for {email}.")
project_id = project.project_id return
print(f"- Project: {project_id}")
print(f"Found {len(projects)} projects. Processing...")
for project in projects:
project_id = project.project_id
print(f"- Project: {project_id}")
if action == 'create':
if enable_api(project_id, creds): if enable_api(project_id, creds):
key = create_api_key(project_id, creds) key = create_api_key(project_id, creds)
if key: if key:
save_api_key(email, project_id, key.key_string) save_api_key(email, project_id, key.key_string)
elif action == 'delete':
delete_api_keys(project_id, creds)
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 API error occurred while processing account {email}: {err}")
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 API error occurred while processing account {email}: {err}")
def get_credentials_for_email(email): def get_credentials_for_email(email):
"""Handles the OAuth2 flow for a given email.""" """Handles the OAuth2 flow for a given email."""
@@ -153,6 +177,35 @@ def create_api_key(project_id, credentials):
print(f"Error creating API key for project {project_id}: {err}") print(f"Error creating API key for project {project_id}: {err}")
return None return None
def delete_api_keys(project_id, credentials):
"""Deletes all API keys with the display name 'Gemini API Key'."""
try:
api_keys_client = api_keys_v2.ApiKeysClient(credentials=credentials)
parent = f"projects/{project_id}/locations/global"
keys = api_keys_client.list_keys(parent=parent)
keys_to_delete = [key for key in keys if key.display_name == "Gemini API Key"]
if not keys_to_delete:
print(f" No 'Gemini API Key' found to delete.")
return
print(f" Found {len(keys_to_delete)} key(s) with display name 'Gemini API Key'. Deleting...")
for key in keys_to_delete:
try:
request = api_keys_v2.DeleteKeyRequest(name=key.name)
operation = api_keys_client.delete_key(request=request)
operation.result() # Wait for completion
print(f" Successfully deleted key: {key.uid}")
except google_exceptions.GoogleAPICallError as err:
print(f" Error deleting key {key.uid}: {err}")
except google_exceptions.PermissionDenied as err:
print(f" Permission denied to list or delete API keys for project {project_id}. Skipping.")
except google_exceptions.GoogleAPICallError as err:
print(f" An API error occurred while deleting keys for project {project_id}: {err}")
def save_api_key(email, project_id, api_key): def save_api_key(email, project_id, api_key):
"""Saves the API key to a file, including the project ID.""" """Saves the API key to a file, including the project ID."""
filename = f"{email}.keys.txt" filename = f"{email}.keys.txt"