you the services pricing must following estimate cost consider cloudfront calculate aws python cdn amazon-cloudfront

python - the - Creación de URL firmadas para Amazon CloudFront



to estimate the cost of amazon cloudfront you must consider (5)

Versión corta: ¿Cómo hago que las URL firmadas sean "on-demand" para imitar el comportamiento X-Accel-Redirect de Nginx (es decir, proteger las descargas) con Amazon CloudFront / S3 usando Python?

Tengo un servidor Django en funcionamiento con un front-end Nginx. Me han acosado las solicitudes y recientemente tuve que instalarlo como una aplicación WSGI Tornado para evitar que se bloquee en el modo FastCGI.

Ahora tengo un problema con el bloqueo de mi servidor (es decir, la mayor parte de su ancho de banda se está agotando) debido a demasiadas solicitudes de medios, he estado investigando CDN y creo que Amazon CloudFront / S3 sería la solución adecuada para mí.

He estado usando el encabezado X-Accel-Redirect de Nginx para proteger los archivos de descargas no autorizadas, pero no tengo esa capacidad con CloudFront / S3; sin embargo, ofrecen URL firmadas. No soy un experto en Python por mucho y definitivamente no sé cómo crear correctamente una URL firmada, así que esperaba que alguien tuviera un enlace sobre cómo hacer que estas URL estuvieran "on-demand" o estuviera dispuesto a explicar cómo hacerlo. Aquí, sería muy apreciado.

Además, ¿es esta la solución adecuada, incluso? No estoy muy familiarizado con los CDN, ¿hay un CDN que sea más adecuado para esto?


Como muchos ya han comentado, la respuesta inicialmente aceptada no se aplica a Amazon CloudFront, de hecho, en la medida en que Servir contenido privado a través de CloudFront requiere el uso de URL firmadas dedicadas de CloudFront . En consecuencia, la respuesta de Secretmike ha sido correcta, pero está obsoleta después de que él mismo se tomó el tiempo y se agregó soporte para generar URL firmadas para CloudFront (¡muchas gracias por esto!).

boto ahora es compatible con un método dedicado a create_signed_url y la antigua dependencia binaria M2Crypto también se ha reemplazado recientemente con una implementación de Python RSA puro , consulte No use M2Crypto para la firma de URL en la nube .

Como cada vez más común, uno puede encontrar uno o más buenos ejemplos de uso dentro de las pruebas unitarias relacionadas (ver test_signed_urls.py ), por ejemplo test_canned_policy(self) - vea setUp(self) para las variables referenciadas self.pk_id y self.pk_str (obviamente necesitarás tus propias llaves):

def test_canned_policy(self): """ Generate signed url from the Example Canned Policy in Amazon''s documentation. """ url = "http://d604721fxaaqy9.cloudfront.net/horizon.jpg?large=yes&license=yes" expire_time = 1258237200 expected_url = "http://example.com/" # replaced for brevity signed_url = self.dist.create_signed_url( url, self.pk_id, expire_time, private_key_string=self.pk_str) # self.assertEqual(expected_url, signed_url)


Esta característica ya es compatible con Botocore , que es la biblioteca subyacente de Boto3, la última versión oficial de AWS SDK para Python . (La siguiente muestra requiere la instalación del paquete rsa, pero también puede usar otro paquete RSA, simplemente defina su propio "firmante RSA normalizado").

El uso se ve así:

from botocore.signers import CloudFrontSigner # First you create a cloudfront signer based on a normalized RSA signer:: import rsa def rsa_signer(message): private_key = open(''private_key.pem'', ''r'').read() return rsa.sign( message, rsa.PrivateKey.load_pkcs1(private_key.encode(''utf8'')), ''SHA-1'') # CloudFront requires SHA-1 hash cf_signer = CloudFrontSigner(key_id, rsa_signer) # To sign with a canned policy:: signed_url = cf_signer.generate_presigned_url( url, date_less_than=datetime(2015, 12, 1)) # To sign with a custom policy:: signed_url = cf_signer.generate_presigned_url(url, policy=my_policy)

Descargo de responsabilidad: Soy el autor de ese PR.


Esto es lo que uso para crear una política para que pueda dar acceso a varios archivos con la misma "firma":

import json import rsa import time from base64 import b64encode url = "http://your_domain/*" expires = int(time.time() + 3600) pem = """-----BEGIN RSA PRIVATE KEY----- ... -----END RSA PRIVATE KEY-----""" key_pair_id = ''ABX....'' policy = {} policy[''Statement''] = [{}] policy[''Statement''][0][''Resource''] = url policy[''Statement''][0][''Condition''] = {} policy[''Statement''][0][''Condition''][''DateLessThan''] = {} policy[''Statement''][0][''Condition''][''DateLessThan''][''AWS:EpochTime''] = expires policy = json.dumps(policy) private_key = rsa.PrivateKey.load_pkcs1(pem) signature = b64encode(rsa.sign(str(policy), private_key, ''SHA-1'')) print ''?Policy=%s&Signature=%s&Key-Pair-Id=%s'' % (b64encode(policy), signature, key_pair_id)

Puedo usarlo para todos los archivos bajo http://your_domain/* por ejemplo:

http://your_domain/image2.png?Policy... http://your_domain/image2.png?Policy... http://your_domain/file1.json?Policy...


La respuesta de secretmike funciona, pero es mejor usar rsa lugar de M2Crypto .

Utilicé boto que usa rsa .

import boto from boto.cloudfront import CloudFrontConnection from boto.cloudfront.distribution import Distribution expire_time = int(time.time() +3000) conn = CloudFrontConnection(''ACCESS_KEY_ID'', ''SECRET_ACCESS_KEY'') ##enter the id or domain name to select a distribution distribution = Distribution(connection=conn, config=None, domain_name='''', id='''', last_modified_time=None, status='''') signed_url = distribution.create_signed_url(url=''YOUR_URL'', keypair_id=''YOUR_KEYPAIR_ID_example-APKAIAZVIO4BQ'',expire_time=expire_time,private_key_file="YOUR_PRIVATE_KEY_FILE_LOCATION")

Usa la boto documentation


Las URL firmadas de Amazon CloudFront funcionan de manera diferente a las URL firmadas de Amazon S3. CloudFront utiliza firmas RSA basadas en un par de claves de CloudFront independiente que debe configurar en su página de Credenciales de cuenta de Amazon. Aquí hay algo de código para generar una URL de tiempo limitado en Python usando la biblioteca M2Crypto :

Crear un par de llaves para CloudFront

Creo que la única forma de hacerlo es a través del sitio web de Amazon. Vaya a la página "Cuenta" de AWS y haga clic en el enlace "Credenciales de seguridad". Haga clic en la pestaña "Pares de claves" y luego haga clic en "Crear un nuevo par de claves". Esto generará un nuevo par de claves para usted y descargará automáticamente un archivo de clave privada (pk-xxxxxxxxx.pem). Mantenga el archivo clave seguro y privado. También anote el "Id. De par de llaves" de amazon, ya que lo necesitaremos en el siguiente paso.

Generar algunas URL en Python

A partir de la versión 2.0 de Boto, no parece haber soporte para generar URL firmadas de CloudFront. Python no incluye rutinas de cifrado RSA en la biblioteca estándar, por lo que tendremos que usar una biblioteca adicional. He usado M2Crypto en este ejemplo.

Para una distribución que no se transmita, debe usar la URL de Cloudfront completa como recurso, sin embargo, para la transmisión solo usamos el nombre del objeto del archivo de video. Vea el código a continuación para ver un ejemplo completo de cómo generar una URL que solo dura 5 minutos.

Este código se basa libremente en el código de ejemplo de PHP proporcionado por Amazon en la documentación de CloudFront.

from M2Crypto import EVP import base64 import time def aws_url_base64_encode(msg): msg_base64 = base64.b64encode(msg) msg_base64 = msg_base64.replace(''+'', ''-'') msg_base64 = msg_base64.replace(''='', ''_'') msg_base64 = msg_base64.replace(''/'', ''~'') return msg_base64 def sign_string(message, priv_key_string): key = EVP.load_key_string(priv_key_string) key.reset_context(md=''sha1'') key.sign_init() key.sign_update(message) signature = key.sign_final() return signature def create_url(url, encoded_signature, key_pair_id, expires): signed_url = "%(url)s?Expires=%(expires)s&Signature=%(encoded_signature)s&Key-Pair-Id=%(key_pair_id)s" % { ''url'':url, ''expires'':expires, ''encoded_signature'':encoded_signature, ''key_pair_id'':key_pair_id, } return signed_url def get_canned_policy_url(url, priv_key_string, key_pair_id, expires): #we manually construct this policy string to ensure formatting matches signature canned_policy = ''{"Statement":[{"Resource":"%(url)s","Condition":{"DateLessThan":{"AWS:EpochTime":%(expires)s}}}]}'' % {''url'':url, ''expires'':expires} #sign the non-encoded policy signature = sign_string(canned_policy, priv_key_string) #now base64 encode the signature (URL safe as well) encoded_signature = aws_url_base64_encode(signature) #combine these into a full url signed_url = create_url(url, encoded_signature, key_pair_id, expires); return signed_url def encode_query_param(resource): enc = resource enc = enc.replace(''?'', ''%3F'') enc = enc.replace(''='', ''%3D'') enc = enc.replace(''&'', ''%26'') return enc #Set parameters for URL key_pair_id = "APKAIAZVIO4BQ" #from the AWS accounts CloudFront tab priv_key_file = "cloudfront-pk.pem" #your private keypair file # Use the FULL URL for non-streaming: resource = "http://34254534.cloudfront.net/video.mp4" #resource = ''video.mp4'' #your resource (just object name for streaming videos) expires = int(time.time()) + 300 #5 min #Create the signed URL priv_key_string = open(priv_key_file).read() signed_url = get_canned_policy_url(resource, priv_key_string, key_pair_id, expires) print(signed_url) #Flash player doesn''t like query params so encode them if you''re using a streaming distribution #enc_url = encode_query_param(signed_url) #print(enc_url)

Asegúrese de configurar su distribución con un parámetro TrustedSigners establecido en la cuenta que tiene su par de llaves (o "Self" si es su propia cuenta)

Consulte Cómo comenzar con la transmisión segura de AWS CloudFront con Python para ver un ejemplo completo de cómo configurar esto para la transmisión con Python.