Était-ce utile?

La solution

Amazon CloudFront URL Signed travail différemment Amazon S3 signé URL. CloudFront utilise des signatures RSA à partir d'une paire de clés CloudFront séparée que vous devez mettre en place dans votre page compte Informations d'identification Amazon. Voici un code pour générer effectivement une URL limitée dans le temps en Python en utilisant le M2Crypto bibliothèque:

Créer une paire de clés pour CloudFront

Je pense que la seule façon de le faire est par le biais du site Web d'Amazon. Allez dans votre AWS page « compte » et cliquez sur le lien « Informations d'identification de sécurité ». Cliquez sur l'onglet « paires de clés », puis cliquez sur « Créer une nouvelle paire de clés ». Cela va générer une nouvelle paire de clés pour vous et télécharger automatiquement un fichier de clé privée (pk-xxxxxxxxx.pem). Gardez le fichier de clé privée et sécurité. Notez également le « ID paire de clés » de amazon que nous en aurons besoin à l'étape suivante.

Générer des URL en Python

de la version 2.0 de Boto il ne semble pas y avoir de soutien pour générer des URL signées CloudFront. Python ne comprend pas les routines de chiffrement RSA dans la bibliothèque standard que nous devrons utiliser une bibliothèque supplémentaire. Je l'ai utilisé M2Crypto dans cet exemple.

Pour une distribution non-diffusion en continu, vous devez utiliser l'URL complète CloudFront comme ressource, mais pour le streaming, nous utilisons uniquement le nom d'objet du fichier vidéo. Voir le code ci-dessous pour un exemple complet de générer une URL qui ne dure que 5 minutes.

Ce code est vaguement basé sur l'exemple de code PHP fourni par Amazon dans la documentation 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)

Assurez-vous que vous configurez votre distribution avec un paramètre TrustedSigners réglé sur le compte tenue de votre paire de clés (ou « Auto » si elle est votre propre compte)

Voir Mise en route avec AWS sécurisé CloudFront le streaming avec Python pour un exemple entièrement travaillé sur cette mise en place pour le streaming avec Python

Autres conseils

Cette fonctionnalité est maintenant déjà pris en charge Botocore, qui est la bibliothèque sous-jacente de Boto3, le dernier SDK AWS officiel pour Python . (L'exemple suivant nécessite l'installation du package rsa, mais vous pouvez utiliser un autre package RSA aussi, il suffit de définir votre propre « RSA normalisée signeur ».)

L'utilisation ressemble à ceci:

    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)

Disclaimer:. Je suis l'auteur de ce PR

Comme beaucoup l'ont déjà commenté, le initialement accepté réponse ne s'applique à Amazon CloudFront en fait, dans la mesure où au service de contenu privé par le biais CloudFront nécessite l'utilisation de dédié noreferrer CloudFront URL signées - ce donc secretmike réponse a été correct, mais il est quant à lui dépassé après avoir pris le temps lui-même et Ajout du support pour générer URL signées pour CloudFront (merci beaucoup pour cela!).

Boto prend désormais en charge un dédié pur-Python mise en œuvre RSA ainsi, voir ne pas utiliser M2Crypto de signature URL CloudFront.

Comme de plus en plus commune, on peut trouver un ou plusieurs bons exemples d'utilisation dans les tests unitaires connexes (voir test_signed_urls.py ), par exemple test_canned_policy (auto) - voir setUp (auto) pour les variables référencées self.pk_idand self.pk_str (vous aurez évidemment besoin de vos propres clés):

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)

La réponse de secretmike fonctionne, mais il est préférable d'utiliser rsa au lieu de M2Crypto.

boto qui utilise 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")

Utilisez le boto documentation

est ce que je l'utilise pour créer une politique afin que je puisse donner accès à plusieurs fichiers avec le même « signature »:

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)

Je peux l'utiliser pour tous les fichiers sous http://your_domain/* par exemple:

 http://your_domain/image2.png?Policy...
 http://your_domain/image2.png?Policy...
 http://your_domain/file1.json?Policy...
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top