# Amazon S3 和 CloudFront:分步指南 将私有 S3 存储桶连接到 DRM-X 6.0,配置权限受限的 IAM、浏览器 CORS 和 CloudFront HTTPS 分发,并完成上传验证。 加密视频和 DRM 许可证通过不同路径传输 CDN 负责传输加密视频。您的后端检查观看权限,DRM 许可证服务则授权兼容设备解密播放。 - 01**存储 / CDN** 向播放器传输加密媒体。 - 02**您的后端** 确认用户有权观看后,向 DRM-X 请求播放授权。 - 03**DRM-X** 验证播放授权并处理 DRM 许可证请求。 - 04**播放器 + 设备** 使用设备的 DRM 系统获取许可证,并播放加密媒体。 您的后端判断用户是否有权观看,DRM-X 执行签名授权中的播放策略。加密媒体与 DRM 许可证通过各自的服务传送给播放器。 **从私有存储桶到加密媒体公共分发** 创建 S3 存储桶,为 DRM-X 配置限定范围的上传凭据,设置浏览器 CORS,连接 CloudFront,然后上传并获取测试对象。原始视频和私人文件应存放在此分发桶之外。 ## 1. 了解连接方式[#](#architecture) DRM-X 使用签名请求直接上传到 S3。观众通过 CloudFront 的 HTTPS URL 下载加密媒体。保持 S3 的 **Block all public access** 启用;CloudFront 通过 **Origin Access Control (OAC)** 获得限定范围的读取权限。 CloudFront 提供可用于生产环境的 `https://….cloudfront.net` 域名,自定义域名不是必需项。公共分发允许通过 URL 获取对象字节;正确打包加密的媒体仍由 DRM 控制解密。CORS 不提供授权。本指南使用普通的公共 CDN 分发;若需要面向观众的签名 URL 或 Cookie,需另行集成。 ## 2. 创建您的 S3 存储桶[#](#create-bucket) ![AWS S3 创建表单:General purpose、Global namespace 和示例存储桶名称。](https://docs.drm-x.com/assets/storage/s3-create.png)12**1:**选择 General purpose。 **2:** 输入您自己的独特名称。这是一个真实的控制台表单,带有未提交的示例;帐户标题被排除在外。 - 打开**Amazon S3→General purpose buckets→Create bucket**。 - 选择一个地区并记录其代码,例如`us-east-1`。选择**General purpose**。如果要求提供命名空间,请在本演练中使用 **Global namespace**。 - 输入您自己的全局唯一存储桶名称。保持**Object Ownership → ACLs disabled (Bucket owner enforced)**。 - 选中 **Block all public access**。您将通过限定范围的策略授予 CloudFront 访问权限。 - 本指南使用 **Default encryption → Server-side encryption with Amazon S3 managed keys (SSE-S3)**。这是额外的存储加密,不能替代 DRM 打包加密。SSE-KMS 还需要为上传方和 CloudFront 配置 KMS 权限。 - 查看并创建存储桶。不要启用 S3 静态网站托管。 ## 3. 创建权限受限的 IAM 用户和访问密钥[#](#iam-credentials) - 开放**IAM → Policies → Create policy → JSON**。粘贴下面的策略,替换各处的示例存储桶名称。 - 该示例仅允许 `protected/`。如果您使用其他基本路径,请更新前缀条件和对象 ARN。对于存储桶根使用,请删除 ListBucket 前缀条件并对对象使用 `arn:aws:s3:::YOUR_BUCKET/*`。 - 保存策略。打开 **IAM → Users → Create user**,创建没有 AWS Console 访问权限的专用集成用户,并仅附加此策略。 - 打开用户的**Security credentials→Access keys→Create access key**。选择在 AWS 之外运行的应用程序的用例,然后按照提示进行操作。牢牢保留 Access key ID 和 Secret access key 至 DRM-X。 ``` { "Version": "2012-10-17", "Statement": [ { "Sid": "ListProtectedFolder", "Effect": "Allow", "Action": "s3:ListBucket", "Resource": "arn:aws:s3:::customer-drm-media-example", "Condition": { "StringLike": { "s3:prefix": [ "protected", "protected/", "protected/*" ] } } }, { "Sid": "BucketRegion", "Effect": "Allow", "Action": "s3:GetBucketLocation", "Resource": "arn:aws:s3:::customer-drm-media-example" }, { "Sid": "ManageProtectedObjects", "Effect": "Allow", "Action": [ "s3:GetObject", "s3:PutObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::customer-drm-media-example/protected/*" } ] } ``` 请勿使用根密钥或 AdministratorAccess。复制使用 GetObject 和 PutObject;没有单独的 `s3:CopyObject` IAM 操作。重命名也需要 DeleteObject。本指南遵循 DRM-X 当前的访问密钥形式;单独的角色 ARN 并不能替代密钥对。 ## 4. 配置 S3 CORS 用于浏览器上传[#](#bucket-cors) - 打开你的 S3 桶→**Permissions**。 - 滚动到 **Cross-origin resource sharing (CORS) → Edit**。 - 粘贴此 JSON,将 `https://www.example.com` 替换为嵌入您的播放器的网站。保留 DRM-XConsole 原点。在现有存储桶中保留其他所需规则。 - 选择**Save changes**。保持 Block Public Access 启用:CORS 不会公开存储桶。 ``` [ { "AllowedOrigins": [ "https://6.drm-x.com" ], "AllowedMethods": [ "PUT" ], "AllowedHeaders": [ "Content-Type", "x-amz-meta-drmx-sha256" ], "ExposeHeaders": [ "ETag" ], "MaxAgeSeconds": 3600 }, { "AllowedOrigins": [ "https://6.drm-x.com", "https://multi-drm.drm-x.com", "https://www.example.com" ], "AllowedMethods": [ "GET", "HEAD" ], "AllowedHeaders": [ "Range" ], "ExposeHeaders": [ "ETag", "Content-Length", "Content-Range", "Accept-Ranges" ], "MaxAgeSeconds": 3600 } ] ``` 上传直接到 S3,因此 PUTCORS 属于 S3。通过 CloudFront 播放还需要步骤 5 中的 CDN 配置。 ## 5. 创建 CloudFront HTTPS 分发 URL[#](#cloudfront) - 打开 **CloudFront → Distributions → Create distribution**,使用标准分配。如果 AWS 显示引导流程或套餐选择,请在创建资源前确认并选择适合账号的套餐。 - 选择存储桶的普通 **S3 REST origin**,不要使用静态网站端点。按照本指南的文件夹映射方式,将 **Origin path 留空**。 - 选择**Origin access control settings (recommended)**。创建或选择带有 **Sign requests (recommended)** 的 OAC。 - 将 viewer protocol policy 设为 **Redirect HTTP to HTTPS** 或 **HTTPS only**,允许 **GET, HEAD, OPTIONS**。上传直接使用 S3 端点,因此 CloudFront 无需允许 PUT。 - 创建 CloudFront 分配。在**S3 → 存储桶 → Permissions → Bucket policy → Edit**中应用 CloudFront 生成的存储桶策略,并保留其他必需的现有规则。将访问范围限制为该分配的 ARN。下方示例仅允许读取 `protected/`。 - 打开 **CloudFront → Policies → Response headers → Create response headers policy**。按下表配置 CORS,并将策略关联到分配的媒体或默认行为。 - 等待部署完成,复制 **Distribution domain name**。分发 origin 为 `https://YOUR_DISTRIBUTION.cloudfront.net`。 | Response headers policy 字段 | 值 | | --- | --- | | Access-Control-Allow-Origin | 填写播放器网站的确切 origin,并加入用于 DRM-X 测试的 `https://6.drm-x.com` 和 `https://multi-drm.drm-x.com`。 | | Access-Control-Allow-Methods | GET, HEAD, OPTIONS | | Access-Control-Allow-Headers | Range | | Access-Control-Expose-Headers | ETag, Content-Length, Content-Range, Accept-Ranges | | Access-Control-Allow-Credentials | 对此公共加密媒体工作流程禁用。 | | Access-Control-Max-Age | 3600 | | Origin override | 启用,以便 CloudFront 一致地控制面向观看者的 CORS。 | 对于 OPTIONS 预检,附加托管 **CORS-S3Origin** 源请求策略。它将 Origin、Access-Control-Request-Method 和 Access-Control-Request-Headers 转发到 S3。最初仅缓存 GET/HEAD,禁用 OPTIONS 缓存。如果您稍后缓存 OPTIONS,请将这些标头包含在其缓存键中并测试不同的播放器来源;单独转发标头不会将其添加到缓存键中。 ``` { "Version": "2012-10-17", "Statement": [ { "Sid": "AllowThisCloudFrontDistribution", "Effect": "Allow", "Principal": { "Service": "cloudfront.amazonaws.com" }, "Action": "s3:GetObject", "Resource": "arn:aws:s3:::customer-drm-media-example/protected/*", "Condition": { "StringEquals": { "AWS:SourceArn": "arn:aws:cloudfront::111122223333:distribution/EEXAMPLE123" } } } ] } ``` 替换示例 account ID、distribution ID 和存储桶名称。SourceArn 必须指向刚创建的分配。如果修改响应头后仍返回旧缓存,请清除相关测试或媒体路径的缓存。 ### 可选:使用 media.example.com - 请求涵盖您在 **US East (N. Virginia)、us-east-1** 中的主机名的 ACM 公共证书,并完成 DNS 验证。 - 在 CloudFront 分配的**Alternate domain names**中添加域名,并关联证书。 - 在您的 DNS 提供商处,创建指向 CloudFront 主机名的 CNAME 或支持的别名。等待 DNS,证书和分发部署。 - 使用 `https://media.example.com` 作为分发 origin。仅添加 DNS CNAME 不够,还必须在 CloudFront 配置域名及证书。 ## 6. 将 Amazon S3 连接到 DRM-X 6.0[#](#connect-drmx) 打开[Cloud Storage→Connect storage](https://6.drm-x.com/console/cloud-storage)。选择**Amazon S3**。 | 字段 | 输入什么 | | --- | --- | | Display name | 便于识别的名称,例如 Production S3。 | | Bucket name | 确切的名称,不含 `s3://`。 | | Region | 存储桶的确切 AWS 区域代码。 | | Protected-content base path | `protected`,匹配 IAM 和存储桶策略。 | | Public URL prefix | `https://YOUR_DISTRIBUTION.cloudfront.net/protected`或`https://media.example.com/protected`。 | | Access key ID / Secret access key | 专用的 IAM 用户密钥对。 | 示例使用名为 `protected` 的文件夹。存储桶名称不会自动成为文件夹。使用本指南的域名直接映射到存储桶方式时,Public URL prefix 必须包含同一存储文件夹,且只出现一次。 ``` Bucket: customer-drm-media-example Protected-content base path: protected Public URL prefix: https://media.example.com/protected File selected for upload: sample.encrypted.bin Object key in the bucket: protected/sample.encrypted.bin Preview URL: https://media.example.com/protected/sample.encrypted.bin ``` 如需上传到存储桶根目录,将 Protected-content base path 留空,Public URL prefix 只填写分发 origin。除非刻意将存储桶名称用作文件夹,否则不要追加它。使用此映射时保持 CloudFront Origin path 为空。 如果需要,选择默认上传目的地,然后选择**Save and verify**。 S3 API 主机名不是您的 CloudFront 分发 URL。 ### 生成您的 CORS 和匹配的 URL 字段 该工具在您的浏览器中运行。仅输入公共来源;它不要求访问密钥。 播放器网站的 origin请替换示例网址。多个 HTTPS origin 可用空格或逗号分隔。填写嵌入播放器的网站来源,不包含页面路径。工具会自动加入 DRM-X Console 和 Playback Lab。公共分发 origin请输入已连接的自定义域名、已启用的 r2.dev URL 或 CloudFront origin。此处不填写文件夹。存储文件夹(可选)生成配置 复制 CORS JSON ``` ``` Protected-content base path``Public URL prefix``示例对象键``完整 URL 示例`` ## 7. 上传文件并验证其是否有效[#](#test-upload) - 打开 [Cloud Storage](https://6.drm-x.com/console/cloud-storage),选择此存储目标并单击 **Verify location**。成功仅表示 DRM-X 服务器可以列出存储桶内容,不能证明写入权限、浏览器 CORS 或公共分发正常。 - 单击 **Upload encrypted files**,从已有 DRM-X 加密输出包中选择一个小的加密片段。如果没有现成输出包,可使用下方的一次性加密诊断文件。不要上传原始视频或私人文档。 - 等待成功消息。检查文件名和大小是否出现在 Cloud Storage 中。在提供商控制台中的 `protected/` 下找到相同的对象。 - 单击 **Preview URL**,并在浏览器无痕窗口中测试同一对象。无需登录 AWS 或 Cloudflare,文件应可下载或返回 HTTP 200。请测试实际对象;即使对象分发正常,域名根路径仍可能返回 403/404。 - 在播放器网站上检查跨源分发。浏览器 Network 面板中的 `Access-Control-Allow-Origin` 应与播放器页面的 origin 匹配。直接在地址栏下载文件不能验证 CORS;下方命令也可用于检查响应头。 - 测试结束后,仅删除本次创建的临时诊断对象。然后按照 [Desktop Packager 指南](https://docs.drm-x.com/zh-Hans/packaging/desktop),在 Package content 中选择此存储目标,并上传完整的加密输出包。手动上传单个文件不会注册 Published Content ID。 - 在 [Universal Playback Lab](https://multi-drm.drm-x.com/zh-Hans/player) 和您的播放器网站上测试已 Published 的内容。验证视频、音频、跳转及所需设备。能下载二进制文件,并不能证明 DRM 播放正常。 没有加密示例?在 Windows 创建一次性测试文件 在您控制的临时文件夹中的 Windows PowerShell 中运行此命令。它使用仅保存在内存中的一次性 AES 密钥对一条简短的非个人消息进行加密。输出是存储诊断,而不是可播放媒体;它不包含 DRM 内容密钥或客户数据。 ``` $samplePath = Join-Path (Get-Location) 'drmx-storage-check.encrypted.bin' if (Test-Path -LiteralPath $samplePath) { throw 'Choose a new folder; this test file already exists.' } $aes = [System.Security.Cryptography.Aes]::Create() try { $aes.GenerateKey() $aes.GenerateIV() $encryptor = $aes.CreateEncryptor() try { $bytes = [Text.Encoding]::UTF8.GetBytes('DRM-X disposable storage check') $encrypted = $encryptor.TransformFinalBlock($bytes, 0, $bytes.Length) [IO.File]::WriteAllBytes($samplePath, $encrypted) } finally { $encryptor.Dispose() } } finally { $aes.Dispose() } Get-Item -LiteralPath $samplePath | Select-Object Name, Length ``` 上传`drmx-storage-check.encrypted.bin`,验证其大小和 Preview URL,然后将其从存储桶中删除。 ``` curl.exe -I -H "Origin: https://www.example.com" "https://media.example.com/protected/sample.encrypted.bin" ``` 替换两个 URL。预计 HTTP 200 以及与您的播放器网站匹配的允许来源。对于范围传递,带有 `Range: bytes=0-15` 的 GET 请求应返回 HTTP 206 和有效的 Content-Range 标头。保留媒体 MIME 类型:DASH 清单使用 application/dash+xml,HLS 播放列表使用 application/vnd.apple.mpegurl,并且媒体文件必须使用其适当的媒体类型。 ## 8. 排查问题[#](#troubleshooting) | 结果 | 处理方法 | | --- | --- | | 验证通过;浏览器上传失败 | 检查浏览器 Console 和 Network 面板。允许来自 Console 确切 origin 的 PUT CORS,并允许 Content-Type 请求头。检查网络连接,重新尝试以取得新的预签名 URL。 | | 上传返回 403 | 检查对象写入权限、存储桶/文件夹范围、端点、区域、请求到期和时钟。请勿共享签名的上传 URL。 | | 上传成功;公共 URL 返回 403 | 检查是否已启用公共分发,以及域名或 CloudFront 分配是否已部署完成。 | | 公开 URL 返回 404 | 将完整的 URL 与确切的对象键进行比较。检查丢失或重复的文件夹和文件名大小写。 | | URL 可直接打开,但播放器获取失败 | 将播放器页面的 origin 加入 GET/HEAD CORS。检查 CDN 响应头,并清除相关路径的旧缓存响应。 | | 下载成功;播放失败 | 检查加密输出包的发布状态、manifest 路径、MIME 类型和 DRM 许可证授权。参见[播放故障排查](https://docs.drm-x.com/zh-Hans/troubleshooting/playback)。 | **CloudFront 403:**确认 OAC 对请求进行签名,存储桶策略使用正确的分布 ARN 和前缀,并且来源是 S3 REST 端点。保持 S3 Block Public Access 开启。如果您选择 SSE-KMS,请检查 KMS 权限。 ## 官方参考文献[#](#references) - [创建 S3 存储桶](https://docs.aws.amazon.com/AmazonS3/latest/userguide/creating-bucket.html) - [管理 IAM 访问密钥](https://docs.aws.amazon.com/IAM/latest/UserGuide/access-key-self-managed.html) - [S3CORS 配置](https://docs.aws.amazon.com/AmazonS3/latest/userguide/ManageCorsUsing.html) - [CloudFront OAC 和 S3 存储桶策略](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/private-content-restricting-access-to-s3.html) - [CloudFront 响应标头](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/adding-response-headers.html) - [托管源请求策略](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/using-managed-origin-request-policies.html) - [自定义域名和证书](https://docs.aws.amazon.com/AmazonCloudFront/latest/DeveloperGuide/add-domain-existing-distribution.html) 使用 Cloudflare?请参照 [Cloudflare R2 设置指南](https://docs.drm-x.com/zh-Hans/storage/cloudflare-r2)。