Generating Cloud Storage Signed URL from Google Cloud Function without using explicit key file

3 min read 06-10-2024
Generating Cloud Storage Signed URL from Google Cloud Function without using explicit key file


Generating Cloud Storage Signed URLs from Google Cloud Functions: A Keyless Approach

Problem: You want to generate temporary, signed URLs for accessing files in Google Cloud Storage (GCS) from a Google Cloud Function, but you want to avoid storing your service account key file within the function's environment.

Rephrased: Imagine you want to give someone a temporary link to download a file from your GCS bucket. You want to do this using a Cloud Function, but you don't want to store your private key within the function's code, which could be a security risk.

This article will guide you through the process of generating signed URLs for GCS objects using a Google Cloud Function without relying on explicit key files.

Scenario:

Let's assume we have a Cloud Function named generateSignedUrl that receives a file name as input and generates a signed URL for that file. The original approach might look like this:

import os
from google.cloud import storage

def generateSignedUrl(request):
    """Generates a signed URL for a given file in GCS."""
    file_name = request.args.get('file_name')
    bucket_name = os.environ.get('BUCKET_NAME')

    # **This is the problem:** We are using a service account key file
    storage_client = storage.Client.from_service_account_json('path/to/key.json')
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(file_name)

    # Generate signed URL
    url = blob.generate_signed_url(expiration=3600, method='GET')
    return url

The issue with this approach:

Storing your service account key file directly within your Cloud Function's environment introduces a security risk. If your function's code is compromised, the key file could be exposed, potentially leading to unauthorized access to your GCS bucket.

Keyless Approach:

The preferred method is to utilize Google Cloud's Identity and Access Management (IAM) and the google-cloud-storage library's StorageClient object. Here's how:

  1. Create a Service Account:

    • In the Google Cloud Console, navigate to IAM & Admin -> Service Accounts.
    • Create a new service account and grant it the necessary permissions (e.g., roles/storage.objectViewer) to access your GCS bucket.
    • Download the service account's JSON key file.
  2. Set up IAM Binding:

    • Grant the service account the roles/iam.serviceAccountTokenCreator role. This allows the service account to create access tokens.
  3. Update Your Cloud Function:

    • Remove the service account key file from your code.
    • Use google.auth.default to automatically obtain credentials using the service account's private key (which is stored in your Cloud Function's environment variables).
import os
from google.cloud import storage
from google.auth import default

def generateSignedUrl(request):
    """Generates a signed URL for a given file in GCS."""
    file_name = request.args.get('file_name')
    bucket_name = os.environ.get('BUCKET_NAME')

    # Use Google Cloud's default authentication
    credentials, project_id = default()
    storage_client = storage.Client(credentials=credentials)
    bucket = storage_client.bucket(bucket_name)
    blob = bucket.blob(file_name)

    # Generate signed URL
    url = blob.generate_signed_url(expiration=3600, method='GET')
    return url

Why this approach is better:

  • Enhanced Security: By utilizing IAM and google.auth.default, your private key never needs to be stored in the Cloud Function's code, improving security.
  • Simplified Management: Using IAM eliminates the need to manage and rotate key files manually.
  • Scalability: This approach scales easily with your application, as IAM handles the authentication process.

Further Considerations:

  • Fine-grained Access Control: Implement granular permissions for your service account, allowing it to perform only the necessary actions.
  • Expiration Time: Adjust the expiration parameter in generate_signed_url to define the validity period of the generated URL.
  • Resource Management: Regularly review and revoke permissions for your service accounts to ensure secure access to your GCS bucket.

Conclusion:

Generating signed URLs for GCS objects from Cloud Functions without relying on explicit key files is a crucial step in securing your cloud infrastructure. By leveraging IAM and default authentication, you can significantly improve security and simplify your application's development process. Remember to prioritize security best practices and manage permissions effectively to protect your data.