Webhooks для S3

Описание сервиса

Webhooks для S3 - это возможность настраивать отправку HTTP/S запросов по событиям для бакета, используя API. Например, вы можете:

  • настроить обработку и конвертирование файлов после загрузки
  • интегрироваться с любыми внешними системами
  • настроить логирование для объектного хранилища

1. Метод PutBucketNotificationConfiguration

Метод позволяет включить уведомление о некотором событии (PutObject, DeleteObject и т.д) в данном бакете.

На данный момент поддерживаем 1 тип событий - SimpleTopicConfiguration - запрос на url, предоставленный пользователем.

Пример: Требуется, чтобы выпонялся запрос на url http://test.com при PutObject в бакет bucketA объектов, имена которых подходят под маску image/*.png. (пример выполняемого по событию запроса на url в п.2)

Для этого нужно сделать следующий запрос (1):

PUT /?notification HTTP/1.1
Host: bucketA.s3.amazonaws.com

<?xml version="1.0" encoding="UTF-8"?>
<NotificationConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <SimpleTopicConfiguration>
      <Id>1</Id>
      <Event>s3:ObjectCreated:Put</Event>
      <Url>http://test.com</Url>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image/</Value>
            </FilterRule>
            <FilterRule>
               <Name>Suffix</Name>
               <Value>.png</Value>
            </FilterRule>
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration>
</NotificationConfiguration>

В момент выполнения этого запроса сервис mcs s3 валидирует url, выполняя на него следующий запрос (2):

POST http://test.com HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation
content-type: application/json

{
    "Timestamp":"2019-12-26T19:29:12+03:00",
    "Type":"SubscriptionConfirmation",
    "Message":"You have chosen to subscribe to the topic $topic. To confirm the subscription you need to response with calculated signature",
    "TopicArn":"mcs2883541269|bucketA|s3:ObjectCreated:Put",
    "SignatureVersion":1,
    "Token":"RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA"
}

для подтверждения url необходимо в ответ отправить подпись:

POST
content-type: application/json

{"signature":"f9da00de9874d3421897a542241cc1d667fd34d59b97f92922e7286df223c63b"}

Cигнатура вычисляется по формуле:


signature = hmac_sha256(url, hmac_sha256(TopicArn, hmac_sha256(Timestamp, Token)))


в нашем примере:

signature = hmac_sha256(“http://test.com”, hmac_sha256(“mcs2883541269|bucketA|s3:ObjectCreated:Put”, hmac_sha256(“2019-12-26T19:29:12+03:00”, “RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA”)))

При успешном подтверждении url, в ответ на запрос (1) будет отправлен response

HTTP/1.1 200

Правила построения запроса PutBucketNotificationConfiguration:

Схема запроса

PUT /?notification HTTP/1.1
Host: Bucket.s3.amazonaws.com

<?xml version="1.0" encoding="UTF-8"?>
<NotificationConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <SimpleTopicConfiguration>
      <Id>string</Id>
      <Url>string</Url>
      <Event>string</Event>
      ...
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>string</Name>
               <Value>string</Value>
            </FilterRule>
            ...
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration>
   ...
</NotificationConfiguration>

Внутри запроса блоков SimpleTopicConfiguration (правил) может быть несколько, но не более 100.

Каждое правило определяется параметрами:

  • Id
    (опциональный)

    Параметр уникальный для каждого правила - строка не более 256 символов. Если не указан, генерируется сервисом.

  • Event
    (обязательный)

    Определяет группу методов над объектом бакета, при которых инициируется событие.

    Поддерживаемые значения: s3:ObjectCreated:* s3:ObjectCreated:Put s3:ObjectCreated:Copy s3:ObjectCreated:CompleteMultipartUpload s3:ObjectRemoved:* s3:ObjectRemoved:Delete.

    s3:ObjectCreated:* - PutObject, PutObjectCopy, CompleteMultipartUpload
    s3:ObjectCreated:Put - PutObject
    s3:ObjectCreated:Copy - PutObjectCopy
    s3:ObjectCreated:CompleteMultipartUpload - CompleteMultipartUpload
    s3:ObjectRemoved:* - DeleteObject
    s3:ObjectRemoved:Delete - DeleteObject
    

    Events в одном правиле может быть несколько, но они не должны содержать одинаковых методов. То есть в одном правиле не могут быть, например, одновременно указаны events: s3:ObjectCreated:*, s3:ObjectCreated:Copy. Поскольку содержат обзий метод - PutObject.

  • Url

    Урл, на который будет осуществляться запрос при срабатывании события.
    Внутри одного правило может быть указано несколько url’ов, каждый из которых необходимо подтвердить по схеме (2).
    И при срабатывании данного правила будут выполняться запросы на каждый из указанных url’ов.

  • Filter
    (опциональный)

    Данный параметр определяет префикс и/или суффикс. Событие срабатывает для данного объекта, только если его имя оответствует указанному префиксу и суффиксу.

    Например: Filter := ( Prefix = ‘src/’, Suffix = ‘.img’ )

    правило будет выполнено для объекта с ключом src/images/tree.img и не будет выполнено для объекта с ключом src/images/tree.png и pic.img


Если в запросе PutBucketNotificationConfiguration описано несколько правил (блоков SimpleTopicConfiguration) с пересекающимися events, то фильтры не должны пересекаться.

Пример неправильного запроса:

<NotificationConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <SimpleTopicConfiguration>
      <Event>s3:ObjectCreated:Put</Event>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image</Value>
            </FilterRule>
         </S3Key>
      </Filter>
      ...
   </SimpleTopicConfiguration>
   <SimpleTopicConfiguration>
      <Event>s3:ObjectCreated:Put</Event>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>im</Value>
            </FilterRule>
         </S3Key>
      </Filter>
      ...
   </SimpleTopicConfiguration>
</NotificationConfiguration>

В данном запросе описаны 2 правила с одинаковым событием s3:ObjectCreated:Put, префиксы которых пересекаются.


Пример валидного запроса (3):

PUT /?notification HTTP/1.1
Host: bucketA.s3.amazonaws.com

<?xml version="1.0" encoding="UTF-8"?>
<NotificationConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
   <SimpleTopicConfiguration>
      <Id>1</Id>
      <Event>s3:ObjectCreated:Put</Event>
      <Url>http://test321.com</Url>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image/</Value>
            </FilterRule>
            <FilterRule>
               <Name>Suffix</Name>
               <Value>.png</Value>
            </FilterRule>
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration>
   <SimpleTopicConfiguration>
      <Id>2</Id>
      <Event>s3:ObjectRemoved:Delete</Event>
      <Url>http://test123.com</Url>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image/</Value>
            </FilterRule>
            <FilterRule>
               <Name>Suffix</Name>
               <Value>.png</Value>
            </FilterRule>
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration>
</NotificationConfiguration>

После установки этого правила, при удалении объектов из бакета bucketA с именами image/*.png будет выполняться запрос на url http://test123.com, а при загрузке объктов в бакет bucketA с именами image/*.png, будет выполняться запрос на url http://test321.com

2. Срабатывание настроенных правил

При срабатывании события, описанного в одном из настроенных правил SimpleTopicConfiguration, сервисом mcs s3 выполняется запрос на указанный в правиле url:

Для примера установленных правил (3), при загрузкие объектов в бакет bucketA с именами image/*.png, будет приходить следующий запрос:

POST <url> HTTP/1.1
x-amz-sns-messages-type: SubscriptionConfirmation

{ "Records":
    [
        {
            "s3": {
                "object": {
                    "eTag":"aed563ecafb4bcc5654c597a421547b2,
                    "sequencer":1577453615,
                    "key":"some-file-to-bucket",
                    "size":100
                },
            "configurationId":"1",
            "bucket": {
                "name": "bucketA",
                "ownerIdentity": {
                    "principalId":"mcs2883541269"}
                },
                "s3SchemaVersion":"1.0"
            },
            "eventVersion":"1.0",
            "requestParameters":{
                "sourceIPAddress":"185.6.245.156"
            },
            "userIdentity": {
                "principalId":"2407013e-cbc1-415f-9102-16fb9bd6946b"
            },
            "eventName":"s3:ObjectCreated:Put",
            "awsRegion":"ru-msk",
            "eventSource":"aws:s3",
            "responseElements": {
                "x-amz-request-id":"VGJR5rtJ"
            }
        }
    ]
}

Тело запроса в соответствии с API amazon https://docs.aws.amazon.com/AmazonS3/latest/dev/notification-content-structure.html

3. Метод GetBucketNotificationConfiguration

Возвращает текущую конфигурацию правил (SimpleNotificationConfiguration) бакета. Если правила не были установлены для данного бакета, будет возращен пустой элемент NotificationConfiguration.

Request

GET /?notification HTTP/1.1
Host: Bucket.s3.amazonaws.com

Для примера (3) будет отправлен следующий ответ:

Response

HTTP/1.1 200

<?xml version="1.0" encoding="UTF-8"?>
<NotificationConfiguration>
   <SimpleTopicConfiguration>
      <Id>1</Id>
      <Event>s3:ObjectCreated:Put</Event>
      <Url>http://test321.com</Url>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image/</Value>
            </FilterRule>
            <FilterRule>
               <Name>Suffix</Name>
               <Value>.png</Value>
            </FilterRule>
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration>
   <SimpleTopicConfiguration>
      <Id>2</Id>
      <Event>s3:ObjectRemoved:Delete</Event>
      <Url>http://test123.com</Url>
      <Filter>
         <S3Key>
            <FilterRule>
               <Name>Prefix</Name>
               <Value>image/</Value>
            </FilterRule>
            <FilterRule>
               <Name>Suffix</Name>
               <Value>.png</Value>
            </FilterRule>
         </S3Key>
      </Filter>
   </SimpleTopicConfiguration> 
</NotificationConfiguration>