'Python / GCP - GitHub Action & Google OAuth without committing ID
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?
Solution 1:[1]
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: '[email protected]'
# 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
Solution 2:[2]
You should be able to use Workflow Identity Federation in GitHub Actions.
Your code should use a Service Account to authenticate instead of the installed app flow and it will need to use the Service Account flow when run as a GitHub Actions (because there's no way for a human user to intervene in the OAuth approval flow).
See Google's blog post Enable keyless auth from GitHub Actions
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | dyl_m |
Solution 2 | DazWilkin |