Раздача видео из Yandex.Cloud Object Storage
В прошлой статье я рассказал, как и зачем хранить видео в формате HLS. Теперь стоит уточнить пару нюансов как правильно настроить раздачу этого контента.
Ограничение доступа
Если залить файлы при помощи s3cmd
в публично доступный бакет, то выложенное таким образом видео любой желающий сможет встроить на свой сайт. Если же это не то, чего вы хотели, и вы хотите ограничить эту возможность нам нужно
- заливать файлы
s3cmd
указав ключ--acl-private
. Без него s3cmd по умолчанию создает объекты с публичным ACL, который перебивает правила заданные политикой. - задать Политику доступа в бакет.
Сделать это можно выполнив следующую команду:
aws s3api put-bucket-policy --bucket $BUCKET --policy file://policy.json
Содержимое файла policy.json
:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"CanonicalUser": "%IAM_USER_ID%"
},
"Action": "*",
"Resource": [
"arn:aws:s3:::%BUCKET%/*",
"arn:aws:s3:::%BUCKET%"
],
"Condition": {
"StringLike": {
"aws:referer": "https://console.cloud.yandex.*/folders/*/storage/bucket/%BUCKET%*"
}
}
},
{
"Sid": "PublicReadForGetBucketObjects",
"Effect": "Allow",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::%BUCKET%/*",
"arn:aws:s3:::%BUCKET%"
],
"Condition": {
"StringLike": {
"aws:referer": [
"http://%YOUR_SITE%*",
"https://%YOUR_SITE%*"
]
}
}
},
{
"Sid": "Explicit deny to ensure requests are allowed only from a specific domain.",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:GetObject",
"Resource": [
"arn:aws:s3:::%BUCKET%/*",
"arn:aws:s3:::%BUCKET%"
],
"Condition": {
"StringNotLike": {
"aws:referer": [
"http://%YOUR_SITE%*",
"https://%YOUR_SITE%*"
]
}
}
}
]
}
Замените %IAM_USER_ID%
, %BUCKET%
и %YOUR_SITE%
на id вашего пользователя, имя бакета и сайт куда вы хотите выложить видео соответственно.
Разберем политики подробнее.
Первая разрешает доступ к объектам из веб-консоли облака. Без нее вы увидите что-то типа такого.
Вторая политика явно разрешает доступ к объектам если HTTP заголовок Referer начинается с адреса вашего сайта. Третья — запрещает, если он отличен от него.
Эти политики разрешают только чтение, если вы хотите потом дополнительно заливать объекты добавьте политику разрешающую это. Где %SERVICE_ACCOUNT_ID%
— id аккаунта от имени которого выписаны ключи (access_key и secret_key), использующиеся для доступа в бакет.
{
"Sid": "Explicitly Allow Service account all actions",
"Effect": "Allow",
"Principal": {
"CanonicalUser": "`%SERVICE_ACCOUNT_ID%`"
},
"Action": "*",
"Resource": [
"arn:aws:s3:::`%BUCKET%`/*",
"arn:aws:s3:::`%BUCKET%`"
]
}
Соответственно, если кто-то попытается встроить видео напрямую из вашего бакета к себе на сайт, у него ничего не получится. Он вместо этого получит ошибку HTTP/1.1 403 Forbidden
.
Disclaimer
Это не панацея. Этот способ не помешает скачать ваше видео, например при помощи curl
передав правильный HTTP-заголовок.
Зато вам не придется платить за трафик с чужого сайта.
Если же вам кажется, что этих мер недостаточно и вы хотите еще усложнить жизнь тем, кто попытается скопировать видео себе, то вы можете использовать AES-128 шифрование ваших видео. В этом посте я подробно расскажу как это сделать.