使用 AWS Lambda 權杖自動販賣機為 Amazon S3 實作 SaaS 租用戶隔離 - AWS 方案指引

本文為英文版的機器翻譯版本,如內容有任何歧義或不一致之處,概以英文版為準。

使用 AWS Lambda 權杖自動販賣機為 Amazon S3 實作 SaaS 租用戶隔離

由虎斑病房(AWS),斯拉文·佩里亞坦比(AWS)和托馬斯·戴維斯(AWS)創建

環境:PoC 或試點

技術:現代化;軟體 SaaS

AWS 服務:AWS Identity and Access Management;AWS Lambda;Amazon S3;AWS STS

Summary

多租戶 SaaS 應用程式必須實作系統,以確保維護租用戶隔離。當您將租用戶資料存放在相同的 Amazon Web Services (AWS) 資源 (例如多個租用戶在同一個 Amazon Simple Storage Service (Amazon S3) 貯體中存放資料時,您必須確保不會發生跨租戶存取。令牌自動售貨機(TVM)是提供租戶數據隔離的一種方法。這些機器提供了一種獲取令牌的機制,同時抽象生成這些令牌的複雜性。開發人員可以使用 TVM,而無需詳細了解它如何生成令牌。

此模式使用 AWS Lambda 實作 TVM。TVM 會產生一個包含臨時安全性權杖服務 (STS) 登入資料的權杖,這些登入資料會限制對 S3 儲存貯體中單一 SaaS 租用戶資料的存取。

TVM 和此模式提供的程式碼通常與衍生自 JSON Web Token (JWT) 的宣告搭配使用,以將 AWS 資源的請求與承租人範圍的 AWS Identity and Access Management (IAM) 政策建立關聯。您可以使用此模式中的代碼作為基礎來實現 SaaS 應用程序,該應用程序根據 JWT 令牌中提供的聲明生成範圍的臨時 STS 憑據。

先決條件和限制

先決條件

  • 作用中的 AWS 帳戶

  • AWS Command Line Interface (AWS CLI) (AWS CLI) 1.19.0 版或更新版本,已在 macOS、Linux 或視窗上安裝和設定。或者,您也可以使用 AWS CLI 2.1 版或更新版本。

限制

  • 此代碼以 Java 運行,目前不支持其他編程語言。 

  • 範例應用程式不包含 AWS 跨區域或災難復原 (DR) 支援。 

  • 此模式示範 SaaS 應用程式的 Lambda TVM 如何提供範圍的租用戶存取。它不打算用於生產環境。

架構

目標技術堆疊

  • AWS Lambda

  • Amazon S3

  • IAM

  • AWS Security Token Service (AWS STS)

目標架構

工具

AWS 服務

Code

此模式的原始程式碼可作為附件使用,並包含下列檔案:

  • s3UploadSample.jar提供 Lambda 函數的原始程式碼,該函數會將 JSON 文件上傳到 S3 儲存貯體。

  • tvm-layer.zip提供可重複使用的 Java 程式庫,為 Lambda 函數提供權杖 (STS 臨時登入資料),以存取 S3 儲存貯體並上傳 JSON 文件。

  • token-vending-machine-sample-app.zip提供用來建立這些成品和編譯指示的原始程式碼。

若要使用這些檔案,請遵循下一節中的指示。

史诗

任務描述所需技能

確定變量值。

此模式的實現包括幾個必須一致使用的變量名稱。決定應用於每個變數的值,並在後續步驟中提出要求時提供該值。

<AWS Account ID>與您實作此模式的 AWS 帳戶相關聯的 12 位數帳戶 ID。如需如何尋找 AWS cccount ID 的相關資訊,請參閱 IAM 文件中的 AWS 帳戶 ID 及其別名

<AWS Region>您在其中實作此模式的 AWS 區域。如需 AWS 區域的詳細資訊,請參閱 AWS 網站上的區域和可用區域

< sample-tenant-name > ─ 要在應用程式中使用的租用戶名稱。為了簡單起見,建議您僅在此值中使用英數字元,但是您可以使用任何有效的名稱作為 S3 物件金鑰

< sample-tvm-role-name > ─ 附加至執行 TVM 和範例應用程式之 Lambda 函數的 IAM 角色名稱。角色名稱是由不含空格的大寫和小寫字母數字字元組成的字串。您也可以包含下列任何字元:底線 (_)、加號 (+)、等號 (=)、逗號 (,)、句點 (.)、@符號和連字號 (-)。角色名稱在帳戶內必須是唯一的。

< sample-app-role-name > ─ 當 Lambda 函數產生範圍的暫時 STS 登入資料時,所假設的 IAM 角色名稱。角色名稱是由不含空格的大寫和小寫字母數字字元組成的字串。您也可以包含下列任何字元:底線 (_)、加號 (+)、等號 (=)、逗號 (,)、句點 (.)、@符號和連字號 (-)。角色名稱在帳戶內必須是唯一的。

< sample-app-function-name > ─ Lambda 函數的名稱。這是一個長度最多 64 個字符的字符串。

< sample-app-bucket-name > ─ 必須使用範圍為特定租用戶的許可存取的 S3 儲存貯體的名稱。S3 儲存貯體名稱:

  • 長度必須介於 3 與 63 個字元之間。

  • 必須僅由小寫字母、數字、句點 (.) 和連字號 (-) 組成。

  • 必須以字母或數字開頭和結尾。

  • 不得採用 IP 地址格式 (例如,192.168.5.4)。

  • 在分割區內必須是唯一的。分割區是區域的群組。AWS 目前有三個分區:aws (標準區域)、aws-cn (中國區域) 和 aws-us-gov (AWS GovCloud [US] 區域)。

雲端管理員
任務描述所需技能

為範例應用程式建立 S3 儲存貯體。

使用下列 AWS CLI 命令建立 S3 儲存貯體。在程式碼片段中提供 < sample-app-bucket-name > 值:

aws s3api create-bucket --bucket <sample-app-bucket-name>

Lambda 範例應用程式會將 JSON 檔案上傳到此儲存貯體。

雲端管理員
任務描述所需技能

建立 TVM 角色。

使用下列其中一個 AWS CLI 命令建立 IAM 角色。在命令中提供 < sample-tvm-role-name > 值。

對於 macOS 或外殼:

aws iam create-role \ --role-name <sample-tvm-role-name> \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" } ]}'

對於視窗命令列:

aws iam create-role ^ --role-name <sample-tvm-role-name> ^ --assume-role-policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Principal\": {\"Service\": \"lambda.amazonaws.com\"}, \"Action\": \"sts:AssumeRole\"}]}"

呼叫應用程式時,Lambda 範例應用程式會擔任此角色。假設具有範圍政策的應用程式角色的功能,可為程式碼提供更廣泛的存取 S3 儲存貯體的許可。

雲端管理員

建立內嵌 TVM 角色原則。

使用下列其中一個 AWS CLI 命令建立 IAM 政策。在指令中提供 < sample-app-role-name >、和 < > 值。sample-tvm-role-name <AWS Account ID>

對於 macOS 或外殼:

aws iam put-role-policy \ --role-name <sample-tvm-role-name> \ --policy-name assume-app-role \ --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": "sts:AssumeRole", "Resource": "arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>" } ]}'

對於視窗命令列:

aws iam put-role-policy ^ --role-name <sample-tvm-role-name> ^ --policy-name assume-app-role ^ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": \"sts:AssumeRole\", \"Resource\": \"arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>\"}]}"

此原則會附加至 TVM 角色。它為程式碼提供了承擔應用程式角色的能力,該角色具有更廣泛的存取 S3 儲存貯體的權限。

雲端管理員

附加受管理的 Lambda 政策。

使用下列 AWS CLI 命令附加 AWSLambdaBasicExecutionRole IAM 政策。在命令中提供 < sample-tvm-role-name > 值:

aws iam attach-role-policy \ --role-name <sample-tvm-role-name> \ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

對於視窗命令列:

aws iam attach-role-policy ^ --role-name <sample-tvm-role-name> ^ --policy-arn arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole

此受管政策附加到 TVM 角色,以允許 Lambda 將日誌傳送到 Amazon CloudWatch。

雲端管理員
任務描述所需技能

建立應用程式角色。

使用下列其中一個 AWS CLI 命令建立 IAM 角色。在指令中提供 < sample-tvm-role-name >、和 < > 值。sample-app-role-name <AWS Account ID>

對於 macOS 或外殼:

aws iam create-role \ --role-name <sample-app-role-name> \ --assume-role-policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Principal": { "AWS": "arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name>" }, "Action": "sts:AssumeRole" } ]}'

對於視窗命令列:

aws iam create-role ^ --role-name <sample-app-role-name> ^ --assume-role-policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\",\"Principal\": {\"AWS\": \"arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name>\"},\"Action\": \"sts:AssumeRole\"}]}"

Lambda 範例應用程式假設此角色具有範圍政策,以取得 S3 儲存貯體的租戶型存取權。

雲端管理員

建立內嵌應用程式角色原則。

使用下列其中一個 AWS CLI 命令建立 IAM 政策。在指令中提供 < sample-app-role-name sample-app-bucket-name > 和 < > 值。

對於 macOS 或外殼:

aws iam put-role-policy \ --role-name <sample-app-role-name> \ --policy-name s3-bucket-access \ --policy-document '{ "Version": "2012-10-17", "Statement": [ { "Effect": "Allow", "Action": [ "s3:PutObject", "s3:GetObject", "s3:DeleteObject" ], "Resource": "arn:aws:s3:::<sample-app-bucket-name>/*" }, { "Effect": "Allow", "Action": ["s3:ListBucket"], "Resource": "arn:aws:s3:::<sample-app-bucket-name>" } ]}'

對於視窗命令列:

aws iam put-role-policy ^ --role-name <sample-app-role-name> ^ --policy-name s3-bucket-access ^ --policy-document "{\"Version\": \"2012-10-17\", \"Statement\": [{\"Effect\": \"Allow\", \"Action\": [\"s3:PutObject\", \"s3:GetObject\", \"s3:DeleteObject\"], \"Resource\": \"arn:aws:s3:::<sample-app-bucket-name>/*\"}, {\"Effect\": \"Allow\", \"Action\": [\"s3:ListBucket\"], \"Resource\": \"arn:aws:s3:::<sample-app-bucket-name>\"}]}"

此原則會附加至應用程式角色。它提供對 S3 儲存貯體中物件的廣泛存取。當範例應用程式擔任角色時,這些權限的範圍會限制為具有 TVM 動態產生原則的特定承租人。

雲端管理員
任務描述所需技能

下載編譯後的源文件。

下載包含為附件的s3UploadSample.jartvm-layer.zip檔案。中提供了用來建立這些成品和編譯實例的原始程式碼。token-vending-machine-sample-app.zip

雲端管理員

建立 Lambda 圖層。

使用下列 AWS CLI 命令建立 Lambda 層,讓 Lambda 能夠存取 TVM。 

附註:如果您不是從下載的位置執行此命令 tvm-layer.zip,請在--zip-file參數tvm-layer.zip中提供正確的路徑。 

aws lambda publish-layer-version \ --layer-name sample-token-vending-machine \ --compatible-runtimes java11 \ --zip-file fileb://tvm-layer.zip

對於視窗命令列:

aws lambda publish-layer-version ^ --layer-name sample-token-vending-machine ^ --compatible-runtimes java11 ^ --zip-file fileb://tvm-layer.zip

此命令會建立一個 Lambda 層,其中包含可重複使用的 TVM 程式庫。

雲管理員,應用程序開發

建立 Lambda 函數。

使用下列 AWS CLI 命令建立 Lambda 函數。在指令中提供 < sample-tvm-role-name >、、、< sample-app-bucket-name >、以及 < sample-app-role-name > 值。sample-app-function-name <AWS Account ID><AWS Region> 

附註:如果您不是從下載的位置執行此命令s3UploadSample.jar,請在--zip-file參數s3UploadSample.jar中提供正確的路徑。 

aws lambda create-function \ --function-name <sample-app-function-name> \ --timeout 30 \ --memory-size 256 \ --runtime java11 \ --role arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name> \ --handler com.amazon.aws.s3UploadSample.App \ --zip-file fileb://s3UploadSample.jar \ --layers arn:aws:lambda:<AWS Region>:<AWS Account ID>:layer:sample-token-vending-machine:1 \ --environment "Variables={S3_BUCKET=<sample-app-bucket-name>, ROLE=arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>}"

對於視窗命令列:

aws lambda create-function ^ --function-name <sample-app-function-name> ^ --timeout 30 ^ --memory-size 256 ^ --runtime java11 ^ --role arn:aws:iam::<AWS Account ID>:role/<sample-tvm-role-name> ^ --handler com.amazon.aws.s3UploadSample.App ^ --zip-file fileb://s3UploadSample.jar ^ --layers arn:aws:lambda:<AWS Region>:<AWS Account ID>:layer:sample-token-vending-machine:1 ^ --environment "Variables={S3_BUCKET=<sample-app-bucket-name>,ROLE=arn:aws:iam::<AWS Account ID>:role/<sample-app-role-name>}"

這個命令會建立一個 Lambda 函數,並附加了範例應用程式程式碼和 TVM 層。它還設置了兩個環境變量:S3_BUCKETROLE。範例應用程式會使用這些變數來決定要承擔的角色,以及要將 JSON 文件上傳到的 S3 儲存貯體。

雲管理員,應用程序開發
任務描述所需技能

叫用 Lambda 範例應用程式。

使用下列其中一個 AWS CLI 命令,以預期的承載啟動 Lambda 範例應用程式。在指令中提供 < sample-app-function-name sample-tenant-name > 和 < > 值。

對於 macOS 和外殼:

aws lambda invoke \ --function <sample-app-function-name> \ --invocation-type RequestResponse \ --payload '{"tenant": "<sample-tenant-name>"}' \ --cli-binary-format raw-in-base64-out response.json

對於視窗命令列:

aws lambda invoke ^ --function <sample-app-function-name> ^ --invocation-type RequestResponse ^ --payload "{\"tenant\": \"<sample-tenant-name>\"}" ^ --cli-binary-format raw-in-base64-out response.json

此命令會呼叫 Lambda 函數,並在response.json文件中傳回結果。在許多 UNIX 系統上,您可以變更為以將結果直接輸出response.json/dev/stdout到殼層,而無需建立其他檔案。 

注意:在後續呼叫此 Lambda 函數中變更 < sample-tenant-name > 值會變更 JSON 文件的位置以及權杖提供的權限。

雲管理員,應用程序開發

檢視 S3 儲存貯體以查看建立的物件。

瀏覽至您先前建立的 S3 儲存貯體 (< sample-app-bucket-name >)。此儲存貯體包含值為 < sample-tenant-name > 的 S3 物件前綴。在該前綴下,您將找到一個以 UUID 命名的 JSON 文檔。多次叫用範例應用程式會新增更多 JSON 文件。

雲端管理員

檢視範例應用程式的雲觀察日誌。

檢視與名為 < sample-app-function-name > 的 Lambda 函數相關聯的雲端觀察日誌。如需指示,請參閱 AWS Lambda 文件中的存取 AWS Lambda 的 Amazon CloudWatch 日誌。您可以在這些記錄中檢視 TVM 產生的承租人範圍原則。此承租人範圍政策授予 Amazon S3 PutObject、、和 ListBucketAPI 的範例應用程式許可 GetObjectDeleteObject,但僅限於與 < > 關聯的物件前綴。sample-tenant-name在範例應用程式的後續呼叫中,如果您變更 < sample-tenant-name >,TVM 會更新範圍原則,以對應於呼叫承載中提供的租用戶。此動態產生的原則顯示如何透過 SaaS 應用程式中的 TVM 維護承租人範圍的存取。 

TVM 功能在 Lambda 層中提供,因此它可以連接到應用程式所使用的其他 Lambda 函數,而無需複寫程式碼。

如需動態產生原則的圖例,請參閱其他資訊一節。

雲端管理員

相關資源

其他資訊

下列 Amazon Cloudwatch 日誌會以此模式顯示由 TVM 程式碼產生的動態產生的政策。在此屏幕截圖中,< sample-app-bucket-name >DOC-EXAMPLE-BUCKET< sample-tenant-name >test-tenant-1。此範圍政策傳回的 STS 登入資料無法對 S3 儲存貯體中的物件執行任何動作,但與物件 key prefix 相關聯的物件除外。test-tenant-1

附件

若要存取與此文件相關聯的其他內容,請解壓縮下列檔案:attachment.zip