URLs Firmadas en Google Cloud Storage

Tutorial para crear URL Firmadas en Google Cloud Storage y Python

Las URLs firmadas en Google Cloud Storage son una forma segura de brindar acceso temporal a objetos privados almacenados en buckets. Estas URLs especiales contienen información de autenticación, que permite a los usuarios acceder al objeto sin necesidad de tener credenciales de Google Cloud.

Al crear una URL firmada, se especifica un tiempo de expiración, lo que garantiza que el acceso al objeto sea limitado en el tiempo. Las URL firmadas son ideales para compartir archivos grandes con usuarios externos o para permitir descargas desde aplicaciones web sin exponer las credenciales de acceso al bucket.

Las URLs firmadas en Google Cloud Platform (GCP) son enlace generado con una firma digital que proporciona un nivel adicional de seguridad y control sobre el acceso a recursos en la nube. Estas URL incluyen un token de autenticación generado mediante claves criptográficas, lo que permite a los usuarios acceder a recursos específicos solo si poseen la URL firmada correspondiente, lo que ayuda a prevenir accesos no autorizados.

En este tutorial, empezaremos por crear un bucket de Google Cloud Storage, que servirá como nuestro repositorio de datos. Dentro de este bucket, crearemos una carpeta para organizar nuestros archivos y subiremos un archivo de ejemplo.

Para gestionar el acceso a estos datos, utilizaremos Cloud IAM. Crearemos una cuenta de servicio con permisos específicos para administrar únicamente los objetos dentro de nuestro bucket. Esto nos permitirá controlar quién y cómo se accede a nuestros datos.

Posterior a eso, configuraremos una instancia de Compute Engine (una máquina virtual en la nube) y la asociaremos a la cuenta de servicio que creamos. Esto permitirá que la instancia interactúe con los objetos del bucket de forma segura, utilizando la identidad y los permisos de la cuenta de servicio.

Para finalizar el tutorial, descararemos y ejecutaremos un script en Python que nos permitirá generar URLs firmadas para Google Cloud Storage, con una duración de máxima de una hora. Para lograr esto, utilizaremos la "service account" y crearemos un archivo JSON que contiene la clave privada. Este archivo será esencial para que nuestro script pueda firmar las URLs de manera segura y otorgar acceso temporal a los recursos de almacenamiento en la nube.

git clone https://gitlab.com/jpadillaa/cloud-storage-demos.git

El tutorial está grabado paso a paso y está disponible en el siguiente enlace. Llegado el momento cloné el repositorio presentado en la línea anterior.

Es importante resaltar algunos aspectos del video para aclarar los conceptos:

  • En Google Cloud Platform, una clave privada (private key) es un archivo en formato JSON o P12 que se utiliza para autenticar una Service Account.

  • Una Service Account es una identidad de Google Cloud que permite a las aplicaciones y servicios interactuar de forma segura con los recursos de Google Cloud.

  • La clave privada es esencialmente la credencial de la Service Account, que se utiliza para demostrar la identidad de la cuenta al acceder a los recursos de GCP.

  • Esta clave se utiliza en las solicitudes de API o en la configuración de servicios para autenticar la Service Account y autorizar el acceso a los recursos según los permisos asignados a dicha cuenta.

  • Es importante solo otorgar acceso a las claves privadas a los usuarios y servicios que realmente las necesiten. Se debe mantener siempre el principio de menor privilegio para limitar los permisos de acceso.

  • Nunca almacene las claves privadas en un repositorio público. En lugar de compartir las claves directamente, es mejor utilizar sistemas de gestión de secretos como HashiCorp Vault o Google Secret Manager.

  • Añada las extensiones de archivo .json y .p12 al archivo .gitignore para prevenir que se suban accidentalmente al repositorio.

  • Implemente políticas de rotación de claves, donde las claves privadas se regeneran y se actualizan periódicamente. Esto reduce la ventana de exposición en caso de que una clave sea comprometida.

Respecto al código voy a resaltar algunos aspectos que considero relevantes:

from datetime import datetime, timedelta
from google.cloud import storage
from google.oauth2 import service_account

def generate_signed_url(bucket_name, object_name, expiration=3600, credentials_file_path='misw-soluciones-cloud.json'):
    """
    Genera una URL firmada para acceder al objeto en un bucket de Cloud Storage.

    Parámetros:
    - bucket_name: El nombre del bucket de Cloud Storage.
    - object_name: El nombre del objeto dentro del bucket.
    - expiration: Tiempo de expiración en segundos para la URL firmada (opcional, predeterminado: 3600 segundos).
    - credentials_file_path: Ruta al archivo de credenciales de la cuenta de servicio (opcional, predeterminado: 'misw-soluciones-cloud.json').

    Retorna:
    Una URL firmada válida para acceder al objeto durante el tiempo especificado.
    """
    # Crea una instancia del cliente de Cloud Storage con las credenciales de la cuenta de servicio
    credentials = service_account.Credentials.from_service_account_file(credentials_file_path)
    client = storage.Client(credentials=credentials)

    # Obtiene el bucket y el objeto
    bucket = client.bucket(bucket_name)
    blob = bucket.blob(object_name)

    # Genera la URL firmada con la expiración proporcionada en segundos
    signed_url = blob.generate_signed_url(expiration=expiration)

    return signed_url

if __name__ == "__main__":
    # Reemplaza 'nombre-del-bucket' y 'nombre-del-objeto' con tus propios valores
    bucket_name = 'cloud-misw-2'
    object_name = 'upload/foto.png'
    current_time = datetime.now()

    # Genera la URL firmada con una expiración de 1 hora (3600 segundos)
    signed_url = generate_signed_url(bucket_name, object_name, expiration= current_time + timedelta(seconds=3600))
    print("URL firmada:", signed_url)

Librerías Importadas:

  • storage de la biblioteca google.cloud se utiliza para interactuar con Google Cloud Storage.

  • service_account de la biblioteca google.oauth2 se utiliza para autenticarse con Google Cloud utilizando una cuenta de servicio.

Parámetros de la función generate_signed_url():

  • bucket_name: El nombre del bucket de GCS donde se encuentra el objeto.

  • object_name: El nombre del objeto dentro del bucket.

  • expiration: (Opcional) Tiempo de expiración en segundos para la URL firmada (por defecto: 3600 segundos, 1 hora).

  • credentials_file_path: (Opcional) Ruta al archivo JSON de credenciales de la cuenta de servicio (por defecto: "misw-soluciones-cloud.json"). En este caso yo subí el archivo a la misma carpeta del proyecto, por lo cual no le paso el parámetro a la función, para esto el nombre del archivo debe ser idéntico al del código.

Bloque principal (if __name__ == "__main__":)

  • Este bloque de código se ejecuta solo cuando el script se ejecuta directamente, no cuando se importa como un módulo.

  • Define el nombre del bucket (cloud-misw-2) y el nombre del objeto (upload/foto.png). Estos valores corresponden a mi caso específico, el nombre global de su bucket será diferente, por lo que debe actualizar este valor, y probablemente igual con sus directorios y archivos.

  • Obtiene la hora actual (current_time) y llama a la función generate_signed_url con los valores especificados y una expiración de 1 hora a partir de la hora actual.

  • Muestra la URL generada en la consola

Referencias

  1. URLs Firmadas en GCP

  2. Choose the best way to use and authenticate service accounts on Google Cloud

Did you find this article valuable?

Support Jesse Padilla by becoming a sponsor. Any amount is appreciated!