程序问答   发布时间:2022-06-02  发布网站:大佬教程  code.js-code.com
大佬教程收集整理的这篇文章主要介绍了使用Python进行安全的AWS CloudFront流传输入门大佬教程大佬觉得挺不错的,现在分享给大家,也给大家做个参考。

如何解决使用Python进行安全的AWS CloudFront流传输入门?

开发过程中遇到使用Python进行安全的AWS CloudFront流传输入门的问题如何解决?下面主要结合日常开发的经验,给出你关于使用Python进行安全的AWS CloudFront流传输入门的解决方法建议,希望对你解决使用Python进行安全的AWS CloudFront流传输入门有所启发或帮助;

没错,建立此程序需要大量API工作。希望他们尽快在AWS控制台中获得它!

要完成您想要的操作,您需要执行以下步骤,以下将详细介绍:

  1. 创建s3存储桶并上传一些对象(您已经完成了此操作)
  2. 创建一个Cloudfront“原始访问身份”(基本上是一个AWS账户,以允许Cloudfront访问您的s3存储桶)
  3. 修改对象上的ACL,以便仅允许您的Cloudfront Origin Access IDentity读取它们(这可以防止人们绕过Cloudfront并直接进入s3)
  4. 使用基本URL和需要签名URL的目录创建一个Cloudfront发行版
  5. 测试您可以从基本的Cloudfront发行版下载对象,但不能从s3或已签名的Cloudfront发行版下载对象
  6. 创建用于签名URL的密钥对
  7. 使用Python生成一些URL
  8. 测试签名的URL是否有效

最简单的方法是通过AWS控制台,但是为了完整起见,我将展示如何使用boto。Boto代码如下所示:

import boto

#credentials stored in environment AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
s3 = boto.connect_s3()

#bucket name MUST follow dns guIDelines
new_bucket_name = "stream.example.com"
bucket = s3.create_bucket(new_bucket_name)

object_name = "vIDeo.mp4"
key = bucket.new_key(object_name)
key.set_contents_from_filename(object_name)

目前,只能使用API​​执行此步骤。Boto代码在这里:

import boto

#credentials stored in environment AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
cf = boto.connect_cloudfront()

oai = cf.create_origin_access_IDentity(comment='New IDentity for secure vIDeos')

#We need the following two values for later steps:
print("Origin Access IDentity ID: %s" % oai.ID)
print("Origin Access IDentity S3CanonicalUserID: %s" % oai.s3_user_iD)

现在,我们已经拥有了特殊的S3用户帐户(我们在上面创建的S3CanonicalUserID),我们需要授予它访问s3对象的权限。通过打开对象的(而不是存储桶的!)权限标签,单击“添加更多权限”按钮,然后将上面获得的很长的S3CanonicalUserID粘贴到新的“ Grantee”字段中,我们可以轻松地使用AWS控制台执行此操作。确保您授予新的权限“打开/下载”权限。

您也可以使用以下boto脚本在代码中执行此操作:

import boto

#credentials stored in environment AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY
s3 = boto.connect_s3()

bucket_name = "stream.example.com"
bucket = s3.geT_Bucket(bucket_name)

object_name = "vIDeo.mp4"
key = bucket.get_key(object_name)

#Now add read permission to our new s3 account
s3_canonical_user_iD = "<your S3CanonicalUserID from above>"
key.add_user_grant("READ", s3_canonical_user_iD)

请注意,直到2.0版(在撰写本文时尚未正式发布)之前,boto才完全不支持自定义来源和私有发行版。下面的代码从boto 2.0分支中提取了一些代码,并将它们砍在一起以使其正常运行,但这并不是很漂亮。2.0分支处理起来更加优雅-如果可能的话,一定要使用它!

import boto
from boto.cloudfront.diStribution import diStributionConfig
from boto.cloudfront.exception import CloudFrontServerError

import re

def get_domain_from_xml(xml):
    results = re.findall("<Domainname>([^<]+)</Domainname>", xml)
    return results[0]

#custom class to Hack this until boto v2.0 is released
class HackedStreamingdiStributionConfig(diStributionConfig):

    def __init__(self, connection=None, origin='', enabled=false,
                 caller_reference='', cnames=None, comment='',
                 trusted_signers=NonE):
        diStributionConfig.__init__(self, connection=connection,
                                    origin=origin, enabled=enabled,
                                    caller_reference=caller_reference,
                                    cnames=cnames, comment=comment,
                                    trusted_signers=trusted_signers)

    #overrIDe the to_xml() function
    def to_xml(self):
        s = '<?xml version="1.0" enCoding="UTF-8"?>\n'
        s += '<StreamingdiStributionConfig xmlns="http://cloudfront.amazonaws.com/doc/2010-07-15/">\n'

        s += '  <S3Origin>\n'
        s += '    <DNSname>%s</DNSname>\n' % self.origin
        if self.origin_access_IDentity:
            val = self.origin_access_IDentity
            s += '    <OriginAccessIDentity>origin-access-IDentity/cloudfront/%s</OriginAccessIDentity>\n' % val
        s += '  </S3Origin>\n'


        s += '  <CallerReference>%s</CallerReference>\n' % self.caller_reference
        for cname in self.cnames:
            s += '  <Cname>%s</Cname>\n' % cname
        if self.comment:
            s += '  <Comment>%s</Comment>\n' % self.comment
        s += '  <Enabled>'
        if self.enabled:
            s += 'true'
        else:
            s += 'false'
        s += '</Enabled>\n'
        if self.trusted_signers:
            s += '<TrustedSigners>\n'
            for signer in self.trusted_signers:
                if signer == 'Self':
                    s += '  <Self/>\n'
                else:
                    s += '  <AwsAccountnumber>%s</AwsAccountnumber>\n' % signer
            s += '</TrustedSigners>\n'
        if self.logging:
            s += '<Logging>\n'
            s += '  <Bucket>%s</Bucket>\n' % self.logging.bucket
            s += '  <Prefix>%s</Prefix>\n' % self.logging.prefix
            s += '</Logging>\n'
        s += '</StreamingdiStributionConfig>\n'

        return s

    def create(self):
        response = self.connection.make_request('POST',
            '/%s/%s' % ("2010-11-01", "streaming-diStribution"),
            {'Content-Type' : 'text/xml'},
            data=self.to_xml())

        body = response.read()
        if response.status == 201:
            return body
        else:
            raise CloudFrontServerError(response.status, response.reason, body)


cf = boto.connect_cloudfront()

s3_dns_name = "stream.example.com.s3.amazonaws.com"
comment = "example streaming diStribution"
oai = "<OAI ID from step 2 above like E23KRHS6GDUF5L>"

#Create a diStribution that does NOT need signed URLS
hsd = HackedStreamingdiStributionConfig(connection=cf, origin=s3_dns_name, comment=comment, enabled=TruE)
hsd.origin_access_IDentity = oai
basic_dist = hsd.create()
print("diStribution with basic URLs: %s" % get_domain_from_xml(basic_dist))

#Create a diStribution that DOES need signed URLS
hsd = HackedStreamingdiStributionConfig(connection=cf, origin=s3_dns_name, comment=comment, enabled=TruE)
hsd.origin_access_IDentity = oai
#Add some required signers (Self means your own account)
hsd.trusted_signers = ['Self']
signed_dist = hsd.create()
print("diStribution with signed URLs: %s" % get_domain_from_xml(signed_dist))

您现在应该可以验证:

  • stream.example.com.s3.amazonaws.com/vIDeo.mp4-应该提供AccessDenIEd
  • signature_diStribution.cloudfront.net/vIDeo.mp4-应该提供MissingKey(因为未签名URL)
  • basic_diStribution.cloudfront.net/vIDeo.mp4-应该可以正常工作

必须对测试进行调整才能与您的流播放器一起使用,但是基本思想是只有基本的Cloudfront URL应该可以使用。

我认为唯一的方法就是通过亚马逊的网站。进入您的AWS“账户”页面,然后单击“安全凭证”链接。单击“密钥对”选项卡,然后单击“创建新的密钥对”。这将为您生成一个新的密钥对,并自动下载一个私钥文件(pk- xxxxxxxxx.pem)。确保密钥文件安全和私密。还要记下亚马逊的“密钥对ID”,因为下一步将需要它。

从boto 2.0版开始,似乎不支持生成签名的CloudFront URL。Python在标准库中不包含RSA加密例程,因此我们将不得不使用其他库。在此示例中,我使用了M2Crypto。

对于非流媒体分发,您必须使用完整的Cloudfront URL作为资源,但是对于流媒体,我们仅使用视频文件的对象名称。有关生成仅持续5分钟的URL的完整示例,请参见下面的代码。

此代码大致基于Amazon在CloudFront文档中提供的php示例代码。

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(str(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}

    #Now base64 encode it (must be URL safE)
    encoded_policy = aws_url_base64_encode(cAnned_policy)
    #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 = "APKaiAZCZRKVIO4BQ" #from the AWS accounts page
priv_key_file = "cloudfront-pk.pem" #your private keypair file
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)

#Flash player doesn't like query params so encode them
enc_url = encode_query_param(signed_url)
print(enc_url)

希望您现在应该拥有一个类似于以下内容的有效网址:

vIDeo.mp4%3FExpires%3D1309979985%26Signature%3DMUNF7pw1689FhMeSN6JzQmWNVxcaIE9mk1x~KOudJky7anTuX0oAgL~1GW-ON6Zh5NFLBoocX3fUhmC9FusAHtJUzWyJVZLzYT9iLyoyfWMsm2ylCDBqpy5IynFbi8cuajd~CjYdxZBWpxTsPO3yIFNJI~R2AFpWx8qp3fs38Yw_%26Key-Pair-ID%3DAPKaiAZRKVIO4BQ

将其放入您的Js中,您应该具有类似以下内容的内容(来自Amazon CloudFront文档中的php示例):

var so_cAnned = new SWFObject('http://LOCATIOn.domname.com/~jvngkhow/player.swf','mpl','640','360','9');
    so_cAnned.addParam('allowfullscreen','true');
    so_cAnned.addParam('allowscriptaccess','always');
    so_cAnned.addParam('wmode','opaque');
    so_cAnned.addVariable('file','vIDeo.mp4%3FExpires%3D1309979985%26Signature%3DMUNF7pw1689FhMeSN6JzQmWNVxcaIE9mk1x~KOudJky7anTuX0oAgL~1GW-ON6Zh5NFLBoocX3fUhmC9FusAHtJUzWyJVZLzYT9iLyoyfWMsm2ylCDBqpy5IynFbi8cuajd~CjYdxZBWpxTsPO3yIFNJI~R2AFpWx8qp3fs38Yw_%26Key-Pair-ID%3DAPKaiAZRKVIO4BQ');
    so_cAnned.addVariable('streamer','rtmp://s3nzpoyjpct.cloudfront.net/cfx/st');
    so_cAnned.write('cAnned');

如您所见,不是很容易!boto v2将有助于大量设置发行版。我将找出是否有可能在其中获得一些URL生成代码来改进这个很棒的库!

解决方法

我创建了一个S3存储桶,上传了视频,并在CloudFront中创建了一个流分发。使用静态HTML播放器对其进行了测试,并且可以正常工作。我已经通过帐户设置创建了密钥对。目前,我的桌面上有私钥文件。那就是我

我的目标是使Django /
Python网站创建安全的URL,除非这些视频来自我的其中一个页面,否则其他人将无法访问这些视频。问题是我对亚马逊布置事物的方式过敏,而我却变得越来越困惑。

我意识到这将不是StackOverflow上的最佳问题,但我敢肯定,我不能成为唯一无法在如何设置安全的CloudFront /
S3情况下大跌眼镜的傻瓜。非常感谢您的帮助,并愿意(一旦过了两天)就最佳答案给出500磅的奖金。

我有几个问题,一旦回答,就应该成为一种关于如何实现我所追求的目标的解释:

  • 在文档中(接下来是一个示例),周围有很多XML告诉我我需要POST到各个地方处理事情。是否有一个在线控制台可以做到这一点?还是我真的必须通过cURL强制这样做(等等)?

  • 如何为CloudFront创建原始访问身份并将其绑定到我的发行版?我已经阅读了这份文档,但是,从第一点来看,我不知道该怎么做。我的密钥对如何适应呢?

  • 完成后,如何限制S3存储桶仅允许人们通过该身份下载内容?如果这是另一项XML工作,而不是在Web UI上单击,请告诉我应该在何处以及如何将其输入我的帐户。

  • 在Python中,为文件生成过期URL的最简单方法是什么。我已经boto安装了,但看不到如何从流分发中获取文件。

  • 是否有任何应用程序或脚本可能会难以设置此服装?我使用Ubuntu(Linux),但如果仅Windows,则可以在VM中使用XP。我已经看过CloudBerry S3 Explorer Pro,但是它和在线UI一样有意义。

大佬总结

以上是大佬教程为你收集整理的使用Python进行安全的AWS CloudFront流传输入门全部内容,希望文章能够帮你解决使用Python进行安全的AWS CloudFront流传输入门所遇到的程序开发问题。

如果觉得大佬教程网站内容还不错,欢迎将大佬教程推荐给程序员好友。

本图文内容来源于网友网络收集整理提供,作为学习参考使用,版权属于原作者。
如您有任何意见或建议可联系处理。小编QQ:384754419,请注明来意。