# API SNS
## 1. Метод PutBucketNotificationConfiguration
Метод включает уведомление о некотором событии (PutObject, DeleteObject и т.д) в данном бакете.
Придерживаемся api Амазона:
https://docs.aws.amazon.com/AmazonS3/latest/API/API_PutBucketNotificationConfiguration.html.
Поддерживаем на данный момент только правила:
- **CloudFunctionConfiguration** - (полностью совпадает с api aws)
- **SimpleTopicConfiguration** - (исключительно наша реализация)
Правило CloudFunctionConfiguration описывает функцию, которую нужно вызвать, и события, на которые ее нужно вызывать.
Правило SimpleTopicConfiguration описывает url, на который делается запрос и события, на которые этот запрос выполняется.
Пример запроса:
```
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>
<Event>string</Event>
...
<Filter>
<S3Key>
<FilterRule>
<Name>string</Name>
<Value>string</Value>
</FilterRule>
...
</S3Key>
</Filter>
<Id>string</Id>
<Url>string</Url>
</SimpleTopicConfiguration>
...
<CloudFunctionConfiguration>
<Event>string</Event>
...
<Filter>
<S3Key>
<FilterRule>
<Name>string</Name>
<Value>string</Value>
</FilterRule>
...
</S3Key>
</Filter>
<Id>string</Id>
<CloudFunction>string</CloudFunction>
</CloudFunctionConfiguration>
...
</NotificationConfiguration>
````
### Общая концепция NotificationConfiguration:
Конфигурация привязывается на бакет и определяет на какие объекты этого бакета и какие события с этими объектами какое уведомление будет выполняться
```
NotificationConfiguration := { (filter, events), notification }
filter := prefix or/and suffix
notification := lambda/url
```
Конфигурация, навешенная на бакет, может содержать не более 100 правил SimpleTopicConfiguration, CloudFunctionConfiguration.
Каждое правило (SimpleTopicConfiguration или CloudFunctionConfiguration) определяется следующими параметрами:
- **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
```
Синтаксис:
```
<Event>s3:ObjectCreated:Put</Event>
<Event>s3:ObjectRemoved:Delete</Event>
```
Обязательный параметр. Событий может быть несколько, но события не должны пересекаться (относительно методов).
- **Filter**
Фильтр определяется префиксом и/или суффиксом. Действует на имя объекта.
Например: Filter := ( Prefix = 'src/', Suffix = '.img' )
правило будет выполнено для объекта с ключом src/images/tree.img, не будет выполнено для объекта с ключом src/images/tree.png и pic.img
Синтаксис:
```
<Filter>
<S3Key>
<FilterRule>
<Name>Prefix</Name>
<Value>src/</Value>
</FilterRule>
<FilterRule>
<Name>Suffix</Name>
<Value>.img</Value>
</FilterRule>
</S3Key>
</Filter>
```
Фильтр является опциональным параметром и может состоять из 1-2 х правил соответственно с различными FilterRule.Name - Prefix, Suffix
- **CloudFunction** (для CloudFunctionConfiguration)
Имя функции, созданной в mcs lambda, в ARN формате (https://docs.aws.amazon.com/general/latest/gr/aws-arns-and-namespaces.html) :
arn:aws:lambda:\${Region}:\${Account}:function:${FunctionName}
Пример: **arn:aws:lambda:ru-msk:mcs15291412:function:my-new-function**
Синтаксис:
```
<CloudFunction>arn:aws:lambda:ru-msk:mcs15291412:function:my-new-function</CloudFunction>
```
- **Url** (для SimpleTopiconfiguration)
Урл, на который будет осуществляться request по событию.
Синтаксис:
```
<Url>https://some_url.com/things/do</Url>
```
Для проверки проедоставленного url, осуществляется request до указанного урла:
```
POST <url> 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|monday-mcs|s3:ObjectCreated:Put",
"SignatureVersion":1,
"Token":"RPE5UuG94rGgBH6kHXN9FUPugFxj1hs2aUQc99btJp3E49tA"
}
```
Для подтверждения url необходимо отправить следующий Response
```
POST
content-type: application/json
{"signature":"f9da00de9874d3421897a542241cc1d667fd34d59b97f92922e7286df223c63b"}
```
Сигнатура вычисляется по следующему правилу:
```
signature = hmac_sha256(url, hmac_sha256(TopicArn, hmac_sha256(Timestamp, Token)))
hmac_sha256(data, key)
```
Для одного и того же события, определенного в правилах конфигурации, фильтры не должны пересекаться
### Response
```
HTTP/1.1 200
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "ID length exceeded allowed limit of 255",
"ArgumentName" : "Id",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Same ID used for multiple configurations. IDs must be unique.",
"ArgumentName" : "Id",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Configuration is ambiguously defined. Cannot have overlapping suffixes in two rules if the prefixes are overlapping for the same event type.",
"ArgumentName" : "FilterRule",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "The event is not supported for notifications",
"ArgumentName" : "Event",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Configurations overlap. Configurations on the same bucket cannot share a common event type.",
"ArgumentName" : "Event",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidRequest",
"Message" : "Too many configurations submitted. The maximum number of configurations is 100",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidRequest",
"Message" : "Bad format url",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Unable to validate the following destination configurations",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "The ARN is not well formed",
"ArgumentName" : "CloudFunction",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Failed to confirm simple topic because of bad response content-type",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Failed to confirm simple topic because of bad response status",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Failed to confirm simple topic because of bad response body",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Failed to confirm simple topic because of bad response body. No signature",
}
------------
HTTP/1.1 400
{
"Code" : "InvalidArgument",
"Message" : "Failed to confirm simple topic because of signature mismatch",
}
------------
```
### Вызов url в SimpleTopicConfiguration
При срабатывании одного из правил SimpleTopicConfiguration будет выполнен следующий request:
```
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": "monday-mcs",
"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"
}
}
]
}
```
## 2. Метод GetBucketNotificationConfiguration
Возвращает текущую конфигурацию (NotificationConfiguration) бакета. Если конфигурация еще не была привязана к бакету, будет возращен пустой элемент NotificationConfiguration.
Придерживаемся api: https://docs.aws.amazon.com/AmazonS3/latest/API/API_GetBucketNotificationConfiguration.html.
Request
```
GET /?notification HTTP/1.1
Host: Bucket.s3.amazonaws.com
```
Response
```
HTTP/1.1 200
<?xml version="1.0" encoding="UTF-8"?>
<NotificationConfiguration>
<SimpleTopicConfiguration>
<Event>string</Event>
...
<Filter>
<S3Key>
<FilterRule>
<Name>string</Name>
<Value>string</Value>
</FilterRule>
...
</S3Key>
</Filter>
<Id>string</Id>
<Url>string</Url>
</SimpleTopicConfiguration>
...
<CloudFunctionConfiguration>
<Event>string</Event>
...
<Filter>
<S3Key>
<FilterRule>
<Name>string</Name>
<Value>string</Value>
</FilterRule>
...
</S3Key>
</Filter>
<Id>string</Id>
<CloudFunction>string</CloudFunction>
</CloudFunctionConfiguration>
...
</NotificationConfiguration>
```