Search code examples
pythongoogle-cloud-platformworkflowgithub-actionsgoogle-api-python-client

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

  • 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