前言
AWS S3是Amazon最早提供的雲端服務之一, 發展至今也有10幾年的歷史了, 服務的範疇也越來越大, 不單純的只是像DropBox那樣, 讓人放檔案而已, 諸如版本控制, 加解密服務, 部屬靜態網站等等...
基本上在S3上, 檔案是以物件的形式存放的
每個物件都會有一組Key和Value, S3會根據Key Name 來決定物件要被存放的實體位置,
如果物件有相似的Key Name, 則會有根大的機率被放在同一個Partition
mybucket/2018-08-26/photo1.png
mybucket/2018-08-26/photo2.png
S3容許我們存放 0 Bytes ~ 5TB 大的檔案, 但若是使用PUT請求上傳檔案的話, 最大只能接受5GB
物件的儲存類別
S3這是最基本的儲存方式
S3-IA
這是用來存放較不常用的檔案類型, 相對的費用也會比較便宜, 但會根據request的次數來收錢
S3 One Zone IA
跟S3-IA一樣適合用來存放不常用的檔案類型, 差別是沒有備援的機制, 所以當遇上天災人禍時, 資料可能就飛了
Security
基本上剛建立的Bucket預設是都是private但是我們可以透過 Bucket policy, ACLs 來決定存取存取權限
Bucket Policy:
屬於Bucket層級的存取機制
比如說: 我有個skilldata的bucket, 若想開放底下所有的物件, 讓外人可以存取, 可以將Bucket Policy定義如下
{
"Id": "Policy1538888263614",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "Stmt1538872791784",
"Action": [
"s3:GetObject"
],
"Effect": "Allow",
"Resource": "arn:aws:s3:::skilldata/*",
"Principal": "*"
}
]
}
ACLs
屬於物件層級的存取機制
我們可以在這邊加入可以存取此物件的人的帳號
Encryption
Encryption in transit基本上發給S3的請求都會被要求走HTTPS的型式, 在傳輸過程中將資料加密
Server Side Encryption
除此之外我們也可以在後端將檔案進行加密, 目前的加密演算法主要是應用AES256, 每當檔案被上傳到S3之後, 資料會被Data Key加密成密文, 而Data Key本身會被另一支叫做Master Key的金鑰加密, 最後在S3上只會有
1. 密文
2.被加密的Data Key
而根據保管金鑰的方式不同, 加密的選擇可以分成以下三種
Data Key | Master Key | |
SSE-S3 | AWS 管理 | AWS 管理 |
S3-KMS | AWS 管理 | 開發者自行管理 |
SSE-C | 開發者自行管理 | 開發者自行管理 |
SSE-S3:這種方式又稱一鍵加密, 用的人啥都不用管, AWS全部都幫你做完
S3-KMS:
這種方式下, S3會使用我們在KMS上建立的Master Key來產生Data Key以及被加密的Data Key
好處是, 我們可以更有彈性地去管理Master Key, 所以也有辦法知道金鑰的使用狀況
SSE-C:
開發者自行管理這些金鑰
在使用PUT請求時, 我們可以在Header加入x-amz-server-side-encryption: <ENCRYPTION_TYPE> , 就能要求S3替我們做Server Side的加密, 如下
PUT /example-object HTTP/1.1
Host: myBucket.s3.amazonaws.com
Date: Wed, 8 Jun 2016 17:50:00 GMT
Authorization: authorization string
Content-Type: text/plain
Content-Length: 11434
x-amz-meta-author: Janet
Expect: 100-continue
x-amz-server-side-encryption: AES256
[11434 bytes of object data]
其中, Expect:100-Continue指的是S3可以根據Header裡的內容決定要不要接受這個請求, 如果請求被S3拒絕, 那表示Body裡的資料也不會被送到S3
為了安全性考量, 我們可以透過定義Bucket Policy的方式, 強迫上傳檔案的使用者必須啟用加密機制
{
"Version": "2012-10-17",
"Id": "PutObjPolicy",
"Statement": [
{
"Sid": "DenyIncorrectEncryptionHeader",
"Effect": "Deny",
"Principal": "*",
"Action": "s3:PutObject",
"Resource": "arn:aws:s3:::<bucket_name>/*",
"Condition": {
"StringNotEquals": {
"s3:x-amz-server-side-encryption": "AES256"
}
}
}
]
}
CORS
原則上, Bucket裡的物件只能存取同一Bucket裡的物件,除非設定CORS, 將可信任的來源加入到白名單裡
<AllowedOrigin>*</AllowedOrigin>
假設我們使用S3來部屬靜態網站時, 檔案分散在不同的Bucket裡, 如果其中一個html會使用到另一個Bucket裡的css檔案時, 我們可以把此html的web url 加到css的Bucket的<AllowedOrigin>裡面
最佳化
對於大量的GET請求(Get-Intensive Request), 建議可以使用CloudFront 將內容Cache起來, 當有相同請求進來時, 就直接從Cache裡拿資料而由於S3會根據Key Name來放檔案, 所以對於大量的GET\PUT\DELETE請求, 若大部分檔案都放在同一個Partition的話, 會很容易會有I/O Issue以致 Performance變差
比如說, 對於用時間來命名的檔案,如下
mybucket/2018-08-26/photo1.png
mybucket/2018-08-26/photo2.png
若在原本的Key Name上前置一串亂數, 可以迫使S3將檔案放在不同的Partition以避免大量Mix請求時效率變差的問題, 如下所示
mybucket/AE30B-2018-08-26/photo1.png
mybucket/BEA10-2018-08-26/photo2.png
補充
Glacier:
若要使用此類型來存放資料, 必須要能夠容忍3~5個小時的時間來恢復資料, 如果讀取這些資料沒有特別的急迫性, 就很適合使用這個類型
比如說像是資料庫的某些資料或許已經過時很久了, 將來要用到的機率也很低, 我們就可以把這些所謂的冷資料移到Glacier存放
https://aws.amazon.com/tw/blogs/security/how-to-prevent-uploads-of-unencrypted-objects-to-amazon-s3/
留言
張貼留言