For a project using the YouTube API, I am using a function that reads my OAuth 2.0 ID from a JSON file, creates / refreshes the credentials automatically and then generate a service to perform all kind of API requests. I've been running the script locally for a few days now, without any problems. But now I would like to automate my project using GitHub Action and specific triggers.
My function looks roughly like this:
import ast
import googleapiclient.discovery
import googleapiclient.errors
import json
import os
import sys
from google.auth.transport.requests import Request
from google.oauth2.credentials import Credentials
from google_auth_oauthlib.flow import InstalledAppFlow
def get_authenticated_service():
# OAUTH 2.0 ID path
oauth_file = '../tokens/oauth.json'
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
cred = None
if os.path.exists('../tokens/credentials.json'):
# Retrieve credentials
cred = Credentials.from_authorized_user_file('../tokens/credentials.json')
if not cred or not cred.valid: # Cover outdated credentials
if cred and cred.expired and cred.refresh_token:
cred.refresh(Request())
else:
# Create a Flow from 'oauth_file'
flow = InstalledAppFlow.from_client_secrets_file(oauth_file, scopes)
# Run authentification process
cred = flow.run_local_server()
with open('../tokens/credentials.json', 'w') as cred_file:
# Save credentials as a JSON file
json.dump(ast.literal_eval(cred.to_json()), cred_file, ensure_ascii=False, indent=4)
try:
service = googleapiclient.discovery.build('youtube', 'v3', credentials=cred)
return service
except Exception as error:
sys.exit()
The problem is that I share my code with a public repository and I don't want to share / commit my ID (what is in token
folder). I'm just starting to learn how GitHub Action works and I have no idea of how to transpose my current method to something that might do the job in a workflow. Is this even possible?
Following @DazWilkin's answer, I found a way to use the Google API Python Client using a Workflow Identity Federation. It took me a while to figure out how all of this is working, but now I can provide an answer. And "surprisingly", it's quite simple to set up.
After setting-up your Federation, you can add these authentication lines in the desired workflow (YAML file):
steps:
- id: checkout
name: Checkout repository
uses: actions/checkout@v3
- id: auth
name: Authenticate to Google Cloud
uses: google-github-actions/auth@v0
with:
token_format: 'access_token'
access_token_scopes: 'https://www.googleapis.com/auth/youtube.force-ssl'
workload_identity_provider: 'projects/123456789/locations/global/workloadIdentityPools/my-pool/providers/my-provider'
service_account: 'my-service-account@my-project.iam.gserviceaccount.com'
# TODO: Install dependencies, program execution...
The service's creation with the Python client is then done with the google.auth
's default method:
import google.auth
import googleapiclient.discovery
def create_service_workflow():
scopes = ["https://www.googleapis.com/auth/youtube.force-ssl"]
credentials, _ = google.auth.default(scopes=scopes)
service = googleapiclient.discovery.build('youtube', 'v3', credentials=credentials)
return service