Total Pageviews

2024/03/10

AWS Lambda Error:An error occurred (UnauthorizedOperation) when calling the AuthorizeSecurityGroupIngress operation: You are not authorized to perform this operation.

Problem

當我嘗試使用 Lambda function,增加一條 rule 至指定 security group 時,出現以下錯誤:

Test Event Name
MyTest

Response
null

Function Logs
START RequestId: 7f5624bf-430f-4c65-a51f-9060e990b159 Version: $LATEST
An error occurred (UnauthorizedOperation) when calling the AuthorizeSecurityGroupIngress operation: You are not authorized to perform this operation. User: arn:aws:sts::102832830373:assumed-role/AddSGFunction-role-shx93f9g/AddSGFunction is not authorized to perform: ec2:AuthorizeSecurityGroupIngress on resource: arn:aws:ec2:us-east-1:102832830373:security-group/sg-056a6d3af28d29d47 because no identity-based policy allows the ec2:AuthorizeSecurityGroupIngress action. Encoded authorization failure message: u7vWnAW1hpW1M7YZt5LVRybW3WXafRneSDK4jpCisbXWFiI5yS7DAZQBJNuXqUMKsRSSn-pTBiotcINMCxvnICsMzd9e7D61fZgGGwrrnrsSPcwnC6V-SH7pDmEtw_rD8cIHhN1CQIByIzn3waZ0bwQqB7ggufrlDZlf4pVWU860dhL89jes5EP8XAW-cuXnoz156F-11Us2ZToRlSHIFGbsTQhxCjaLTIkKFyLnd45mkgF_24a8VKjqUXz1jcEAfZEM3FgQeCoG7BBKqk9Z_3S-ODAPoBQ4NuGYFfYKTqIGOVx_QEV3HlqC9QEXJ1ylRWoZ2aU94KESR54ak4yk9U6bwZGMz_Y8Lxw2UcQBfI43sdvGQW8Ga6G8yGMLO9qjaFqgRkVBrUZIjpprl0vEo5pN96m8mzdmqdELDR0KUV69VZkLzfevef44zP2Bwo5JaQKhFyzb00eiaZj3AuLSbf7Hyzawp5DKnDa7xasZkHU60sVbDDPnAyWQ98D9felWps-tafPaWVO49rg50UQKAz2lSwDKFLT-BIluOph8ruuJO_0YZyiQJmn3TYMEq3x2uR7IUsYTdugmYAJzmzNHzdIy5YxBPGx7SEvoEX9C_xZIloJLSWkO
END RequestId: 7f5624bf-430f-4c65-a51f-9060e990b159
REPORT RequestId: 7f5624bf-430f-4c65-a51f-9060e990b159	Duration: 3407.09 ms	Billed Duration: 3408 ms	Memory Size: 128 MB	Max Memory Used: 89 MB	Init Duration: 408.87 ms

Request ID
7f5624bf-430f-4c65-a51f-9060e990b159


Root Cause

此 Lambda function 不具備增添 security group rule 的權限



How-To

增添以下權限 ec2:AuthorizeSecurityGroupIngress




Test Result

執行結果

Test Event Name
MyTest

Response
null

Function Logs
START RequestId: 266304a2-53ce-40f0-8918-7782fb6bb3cc Version: $LATEST
Ingress Successfully Set {'Return': True, 'SecurityGroupRules': [{'SecurityGroupRuleId': 'sgr-063e134cb604a00a2', 'GroupId': 'sg-056a6d3af28d29d47', 'GroupOwnerId': '102832830373', 'IsEgress': False, 'IpProtocol': 'tcp', 'FromPort': 80, 'ToPort': 80, 'CidrIpv4': '0.0.0.0/0'}], 'ResponseMetadata': {'RequestId': '58ea616d-28bb-4d65-b544-d61ff7834a33', 'HTTPStatusCode': 200, 'HTTPHeaders': {'x-amzn-requestid': '58ea616d-28bb-4d65-b544-d61ff7834a33', 'cache-control': 'no-cache, no-store', 'strict-transport-security': 'max-age=31536000; includeSubDomains', 'content-type': 'text/xml;charset=UTF-8', 'content-length': '719', 'date': 'Sun, 10 Mar 2024 02:11:17 GMT', 'server': 'AmazonEC2'}, 'RetryAttempts': 0}}
END RequestId: 266304a2-53ce-40f0-8918-7782fb6bb3cc
REPORT RequestId: 266304a2-53ce-40f0-8918-7782fb6bb3cc	Duration: 3649.45 ms	Billed Duration: 3650 ms	Memory Size: 128 MB	Max Memory Used: 89 MB	Init Duration: 324.16 ms

Request ID
266304a2-53ce-40f0-8918-7782fb6bb3cc

確認 security group rule



延伸問題

若 Lambda function 要 revoke security group rule,需賦予以下權限,範例:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Effect": "Allow",
            "Action": "ec2:RevokeSecurityGroupIngress",
            "Resource": "arn:aws:ec2:region:account-id:security-group/sg-xxxxxxxx"
        }
    ]
}

實際例子:
{
    "Version": "2012-10-17",
    "Statement": [
        {
            "Sid": "VisualEditor0",
            "Effect": "Allow",
            "Action": "ec2:RevokeSecurityGroupIngress",
            "Resource": "arn:aws:ec2:us-east-1:102832830373:security-group/sg-056a6d3af28d29d47"
        }
    ]
}



2024/02/19

Using AWS CLI to Encrypt and Decrypt

上傳一個 plain text file 到 AWS CloudShell,並印出內容

[cloudshell-user@ip-10-130-78-240 ~]$ cat ExamplePlaintextFile.txt
abc
123
test

建立一個 AWS KMS Key 如下


透過 AWS CLI 加密原 plain text file,並產生一個 EncryptedFile.txt,並印出 EncryptedFile.txt 內容

[cloudshell-user@ip-10-130-78-240 ~]$ aws kms encrypt --key-id alias/AlbertKey --plaintext fileb://ExamplePlaintextFile.txt --output text --query CiphertextBlob | base64 --decode > EncryptedFile.txt
[cloudshell-user@ip-10-130-78-240 ~]$ cat EncryptedFile.txt
00Y0Tom%`He.08Ó~SGe`VCn5j0h     *H
             "N^";';P䫒}XU'Jڋ?oC


透過 AWS CLI 解密 EncryptedFile.txt 至 DecryptedFile.txt,並印出 DecryptedFile.txt

[cloudshell-user@ip-10-130-78-240 ~]$ aws kms decrypt --ciphertext-blob fileb://EncryptedFile.txt --output text --query Plaintext | base64 --decode > DecryptedFile.txt
[cloudshell-user@ip-10-130-78-240 ~]$ cat DecryptedFile.txt
abc
123
test


How to read Parameter Store values from Lambda function

已在 Parameter Store 建立兩個參數


已建立以下 Lambda function Code
import boto3
import json

def lambda_handler(event, context):
    # 初始化 SSM 客戶端
    ssm = boto3.client('ssm')
    
    # 參數名稱
    parameters_to_get = [
        '/Dev/DBServer/MySQL/db-user',
        '/Dev/DBServer/MySQL/db-pwd'
    ]
    
    # 從 Parameter Store 獲取參數值
    response = ssm.get_parameters(
        Names=parameters_to_get,
        WithDecryption=True  # 如果參數是加密的,設置為 True
    )
    
    # 初始化一個變數來存儲參數名稱和值
    parameters_values = {}
    
    # 檢查並讀取每個參數的值
    for param in response['Parameters']:
        parameters_values[param['Name']] = param['Value']
    
    # 列印參數值
    print(f"Parameter Values: {json.dumps(parameters_values)}")
    
    return {
        'statusCode': 200,
        'body': json.dumps(f"Parameter Values: {parameters_values}")
    }

賦予 Lambda 有讀取 SSM 的權限



執行結果

Test Event Name
MyTest

Response
{
  "statusCode": 200,
  "body": "\"Parameter Values: {'/Dev/DBServer/MySQL/db-pwd': 'mypassword', '/Dev/DBServer/MySQL/db-user': 'admin'}\""
}

Function Logs
START RequestId: 7c95489a-f09d-44b8-9b5e-25968ca0b318 Version: $LATEST
Parameter Values: {"/Dev/DBServer/MySQL/db-pwd": "mypassword", "/Dev/DBServer/MySQL/db-user": "admin"}
END RequestId: 7c95489a-f09d-44b8-9b5e-25968ca0b318
REPORT RequestId: 7c95489a-f09d-44b8-9b5e-25968ca0b318	Duration: 2379.66 ms	Billed Duration: 2380 ms	Memory Size: 128 MB	Max Memory Used: 78 MB	Init Duration: 301.53 ms

Request ID
7c95489a-f09d-44b8-9b5e-25968ca0b318


Create AWS Lambda from CloudFormation

假設已準備好 yaml file,內容如下:

AWSTemplateFormatVersion: '2010-09-09'
Description: 'AWS CloudFormation Sample: AWS Lambda Function with Python.'

Resources:
  HelloWorldFunction:
    Type: 'AWS::Lambda::Function'
    Properties:
      Handler: index.lambda_handler
      Role: !GetAtt LambdaExecutionRole.Arn
      Runtime: python3.8
      Code:
        ZipFile: |
          def lambda_handler(event, context):
              return {
                  'statusCode': 200,
                  'body': 'Hello, World!'
              }
      Timeout: 5

  LambdaExecutionRole:
    Type: 'AWS::IAM::Role'
    Properties:
      AssumeRolePolicyDocument:
        Version: '2012-10-17'
        Statement:
          - Effect: Allow
            Principal:
              Service: lambda.amazonaws.com
            Action: 'sts:AssumeRole'
      Policies:
        - PolicyName: 'lambda-basic-execution'
          PolicyDocument:
            Version: '2012-10-17'
            Statement:
              - Effect: Allow
                Action:
                  - 'logs:CreateLogGroup'
                  - 'logs:CreateLogStream'
                  - 'logs:PutLogEvents'
                Resource: 'arn:aws:logs:*:*:*'

確認 CloudFormation 執行結果



確認 CloudFormation 已建立的 AWS resources



確認所建立的 Lambda Function:



確認 Lambda 執行結果符合預期:

Test Event Name
Test

Response
{
  "statusCode": 200,
  "body": "Hello World!"
}

Function Logs
START RequestId: 665b5e07-c386-4b89-b59c-0a6e00979de0 Version: $LATEST
END RequestId: 665b5e07-c386-4b89-b59c-0a6e00979de0
REPORT RequestId: 665b5e07-c386-4b89-b59c-0a6e00979de0	Duration: 2.07 ms	Billed Duration: 3 ms	Memory Size: 128 MB	Max Memory Used: 39 MB	Init Duration: 129.94 ms

Request ID
665b5e07-c386-4b89-b59c-0a6e00979de0

AWS Lambda Alias

假設我有一支 Lambda function,內容如下:

import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! (Version 1)')
    }

並成功完成 Test:

Test Event Name
MyTest

Response
{
  "statusCode": 200,
  "body": "\"Hello from Lambda! (Version 1)\""
}

Function Logs
START RequestId: f0a719c8-1ffb-499d-942f-206f73dd0045 Version: $LATEST
END RequestId: f0a719c8-1ffb-499d-942f-206f73dd0045
REPORT RequestId: f0a719c8-1ffb-499d-942f-206f73dd0045	Duration: 11.58 ms	Billed Duration: 12 ms	Memory Size: 128 MB	Max Memory Used: 34 MB

Request ID
f0a719c8-1ffb-499d-942f-206f73dd0045


透過 AWS CLI 發佈第一個版本:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda publish-version --function-name HelloWorldFunction
{
    "FunctionName": "HelloWorldFunction",
    "FunctionArn": "arn:aws:lambda:us-east-1:827888540138:function:HelloWorldFunction:1",
    "Runtime": "python3.12",
    "Role": "arn:aws:iam::827888540138:role/service-role/HelloWorldFunction-role-2pj1z9b2",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 277,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-02-19T00:51:48.000+0000",
    "CodeSha256": "FGaiUQRyAxEPhQmLcV9dUlGl1qIvgba7Ae1zCInXC3g=",
    "Version": "1",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "d42bcc86-34a7-4ce4-a739-16e6d785c3af",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {
        "ApplyOn": "None",
        "OptimizationStatus": "Off"
:...skipping...


修改 Lambda function,程式內容如下:

import json

def lambda_handler(event, context):
    # TODO implement
    return {
        'statusCode': 200,
        'body': json.dumps('Hello from Lambda! (Version 2)')
    }


發佈第二個版本:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda publish-version --function-name HelloWorldFunction
{
    "FunctionName": "HelloWorldFunction",
    "FunctionArn": "arn:aws:lambda:us-east-1:827888540138:function:HelloWorldFunction:2",
    "Runtime": "python3.12",
    "Role": "arn:aws:iam::827888540138:role/service-role/HelloWorldFunction-role-2pj1z9b2",
    "Handler": "lambda_function.lambda_handler",
    "CodeSize": 276,
    "Description": "",
    "Timeout": 3,
    "MemorySize": 128,
    "LastModified": "2024-02-19T01:02:46.000+0000",
    "CodeSha256": "xzDR5dGezW2VtWOvVraE1yY6kIQXIKy7UBS/1WDMeyw=",
    "Version": "2",
    "TracingConfig": {
        "Mode": "PassThrough"
    },
    "RevisionId": "299ba2c8-c055-4314-9b29-bbd9e9332e96",
    "State": "Active",
    "LastUpdateStatus": "Successful",
    "PackageType": "Zip",
    "Architectures": [
        "x86_64"
    ],
    "EphemeralStorage": {
        "Size": 512
    },
    "SnapStart": {


建立 Alias,PROD 指向 Version 1、DEV 指向 Version 2

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda create-alias --function-name HelloWorldFunction --name PROD --function-version 1
{
    "AliasArn": "arn:aws:lambda:us-east-1:827888540138:function:HelloWorldFunction:PROD",
    "Name": "PROD",
    "FunctionVersion": "1",
    "Description": "",
    "RevisionId": "dfc0cdd9-5bf8-4483-bd0b-0cc098e4a70e"
}
[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda create-alias --function-name HelloWorldFunction --name DEV --function-version 2
{
    "AliasArn": "arn:aws:lambda:us-east-1:827888540138:function:HelloWorldFunction:DEV",
    "Name": "DEV",
    "FunctionVersion": "2",
    "Description": "",
    "RevisionId": "2526ec87-e93b-4189-828a-bab954fcf019"
}


執行 PROD alais,結果如下:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda invoke --function-name "HelloWorldFunction:PROD" outputfile.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "1"
}


執行 DEV alais,結果如下:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda invoke --function-name "HelloWorldFunction:DEV" outputfile.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "2"
}


Version 2 完成測試後,將 PROD 指向 Version 2:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda update-alias --function-name "HelloWorldFunction" --name "PROD" --function-version "2"
{
    "AliasArn": "arn:aws:lambda:us-east-1:827888540138:function:HelloWorldFunction:PROD",
    "Name": "PROD",
    "FunctionVersion": "2",
    "Description": "",
    "RevisionId": "9b3c5ce4-4c46-4bba-a5bf-ceb8291e090d"
}


執行 PROD alais,結果如下:

[cloudshell-user@ip-10-132-51-15 ~]$ aws lambda invoke --function-name "HelloWorldFunction:PROD" outputfile.txt
{
    "StatusCode": 200,
    "ExecutedVersion": "2"
}

2024/02/17

如何透過 AWS Lambda 啟動/關閉 EC2

前置作業

假設我已經建立好一台 EC2


已準備一支用 Python 語法寫的 AWS Lambda function(當 EC2 是 Running 狀態時,就 Stop 它;當 EC2 是 Stopped 狀態時,就 Start 它)

import boto3

# 初始化 EC2 客戶端
ec2 = boto3.client('ec2')

def lambda_handler(event, context):
    # 指定要操作的 EC2 實例 ID
    instance_id = 'i-0ebe0819d2efb0cff'

    # 獲取實例的當前狀態
    response = ec2.describe_instances(InstanceIds=[instance_id])
    state = response['Reservations'][0]['Instances'][0]['State']['Name']

    # 根據實例的當前狀態進行操作
    if state == 'running':
        # 如果實例正在運行,則停止它
        stop_response = ec2.stop_instances(InstanceIds=[instance_id])
        action = 'stopped'
    elif state == 'stopped':
        # 如果實例已停止,則啟動它
        start_response = ec2.start_instances(InstanceIds=[instance_id])
        action = 'started'
    else:
        # 如果實例處於其他狀態,不進行操作
        return {
            'statusCode': 400,
            'body': f'Instance {instance_id} is in {state} state, no action taken.'
        }

    # 返回操作結果
    return {
        'statusCode': 200,
        'body': f'Instance {instance_id} has been {action} successfully.'
    }

賦予 AWS Lambda 操作 EC2 的權限



執行測試:(Running => Stopped)

EC2 執行前


Lambda 執行結果


EC2 執行後



執行測試:(Stopped => Running)

EC2 執行前


Lambda 執行結果


EC2 執行後




2024/02/14

AWS S3 + CloudFront + OAI

步驟 1: Create S3 bucket


步驟 2: Upload a image file to  S3 bucket



步驟 3: Create CloudFront distribution 與使用 Origin Access Identity (OAI) 保護 S3 content




步驟 4: Update S3 bucket policy



步驟 5: 等候幾分鐘,待 CloudFront distribution 完成 Deploy



步驟 6: 測試 CloudFront distribution



2024/02/13

如何在 EC2 安裝 AWS SDK for Python (Boto3)

步驟 1: 安裝 Python

[ec2-user@ip-172-31-28-226 ~]$ sudo yum install python3 python3-pip -y


步驟 2: 驗證安裝

ec2-user@ip-172-31-28-226 ~]$ python3 --version
Python 3.9.16


步驟 3: 安裝 AWS SDK for Python (Boto3)

[ec2-user@ip-172-31-28-226 ~]$ pip3 install boto3
Defaulting to user installation because normal site-packages is not writeable
Collecting boto3
  Downloading boto3-1.34.40-py3-none-any.whl (139 kB)
     |████████████████████████████████| 139 kB 5.7 MB/s            
Collecting botocore<1.35.0,>=1.34.40
  Downloading botocore-1.34.40-py3-none-any.whl (12.0 MB)
     |████████████████████████████████| 12.0 MB 41.5 MB/s            
Collecting s3transfer<0.11.0,>=0.10.0
  Downloading s3transfer-0.10.0-py3-none-any.whl (82 kB)
     |████████████████████████████████| 82 kB 378 kB/s              
Requirement already satisfied: jmespath<2.0.0,>=0.7.1 in /usr/lib/python3.9/site-packages (from boto3) (0.10.0)
Requirement already satisfied: python-dateutil<3.0.0,>=2.1 in /usr/lib/python3.9/site-packages (from botocore<1.35.0,>=1.34.40->boto3) (2.8.1)
Requirement already satisfied: urllib3<1.27,>=1.25.4 in /usr/lib/python3.9/site-packages (from botocore<1.35.0,>=1.34.40->boto3) (1.25.10)
Requirement already satisfied: six>=1.5 in /usr/lib/python3.9/site-packages (from python-dateutil<3.0.0,>=2.1->botocore<1.35.0,>=1.34.40->boto3) (1.15.0)
Installing collected packages: botocore, s3transfer, boto3
Successfully installed boto3-1.34.40 botocore-1.34.40 s3transfer-0.10.0


步驟 4: 配置 AWS CLI (請自行設定自己的 AK 與 SK)

[ec2-user@ip-172-31-28-226 ~]$ aws configure
AWS Access Key ID [None]: AKIASHY4YDRZJLQSTQNU
AWS Secret Access Key [None]: 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
Default region name [None]: us-east-1
Default output format [None]: json


步驟 5: 寫一個 Python 程式來列出 S3 bucket

[ec2-user@ip-172-31-28-226 ~]$ vi list_s3_buckets.py 
[ec2-user@ip-172-31-28-226 ~]$ cat list_s3_buckets.py 
import boto3

def list_buckets():
    # 創建一個 S3 服務客戶端
    s3 = boto3.client('s3')
    
    # 列出所有buckets
    response = s3.list_buckets()
    
    # 輸出 bucket name
    print("S3 Buckets:")
    for bucket in response['Buckets']:
        print(f"- {bucket['Name']}")

if __name__ == '__main__':
    list_buckets()


步驟 6: 執行 Python 程式

[ec2-user@ip-172-31-28-226 ~]$ python3 list_s3_buckets.py
S3 Buckets:
- albert-buckert-154142252146

如何安裝與驗證 AWS CLI

安裝 AWS CLI

1. 下載 AWS CLI

[ec2-user@ip-172-31-28-226 ~]$ curl "https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip" -o "awscliv2.zip"
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100 57.3M  100 57.3M    0     0   260M      0 --:--:-- --:--:-- --:--:--  261M


2. 解壓縮下載檔案

[ec2-user@ip-172-31-28-226 ~]$ unzip awscliv2.zip


3. 安裝 AWS CLI

[ec2-user@ip-172-31-28-226 ~]$ sudo ./aws/install
You can now run: /usr/local/bin/aws --version


4. 驗證安裝結果

[ec2-user@ip-172-31-28-226 ~]$ aws --version
aws-cli/2.15.19 Python/3.11.6 Linux/6.1.75-99.163.amzn2023.x86_64 exe/x86_64.amzn.2023 prompt/off


5. 配置 AWS CLI

- AWS Access Key IDAWS Secret Access Key:你可以在 AWS 管理控制台的 IAM 服務中建立一個新的使用者或使用現有的使用者憑證。
- Default region name:輸入你想要操作的 AWS 區域的代碼,例如 us-east-1
- Default output format:輸入你偏好的輸出格式,常見的選項包括 jsontexttable

[ec2-user@ip-172-31-28-226 ~]$ aws configure
AWS Access Key ID [None]: AKIASHY4YDRZJLQSTQNU
AWS Secret Access Key [None]: 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
Default region name [None]: us-east-1
Default output format [None]: json


透過 AWS CLI 進行 S3 操作

1. Create S3 bucket

[ec2-user@ip-172-31-28-226 ~]$ aws s3 mb s3://albert-buckert-154142252146 --region us-east-1
make_bucket: albert-buckert-154142252146


2. List S3 bucket

[ec2-user@ip-172-31-28-226 ~]$ aws s3 ls
2024-02-13 10:02:24 albert-buckert-154142252146


3. Create a file and upload it to S3 bucket

[ec2-user@ip-172-31-28-226 ~]$ echo "Hello World" > hello.txt
[ec2-user@ip-172-31-28-226 ~]$ cat hello.txt
Hello World
[ec2-user@ip-172-31-28-226 ~]$ aws s3 cp hello.txt s3://albert-buckert-154142252146
upload: ./hello.txt to s3://albert-buckert-154142252146/hello.txt 



2024/02/12

Send Fanout Event Notifications with Amazon Simple Queue Service (SQS) and Amazon Simple Notification Service (SNS)

步驟 1: 建立 SNS Topic

[cloudshell-user@ip-10-138-176-84 ~]$ aws sns create-topic --name MyFanoutTopic
{
    "TopicArn": "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic"
}


步驟 2: 建立兩個 SQS Queue
[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs create-queue --queue-name MyQueue1
{
    "QueueUrl": "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue1"
}
[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs create-queue --queue-name MyQueue2
{
    "QueueUrl": "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue2"
}


步驟 3: 取得兩個 SQS Queue 的 Queue Arn
[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs get-queue-attributes --queue-url "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue1" --attribute-names "QueueArn"
{
    "Attributes": {
        "QueueArn": "arn:aws:sqs:us-east-1:473993628677:MyQueue1"
    }
}
[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs get-queue-attributes --queue-url "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue2" --attribute-names "QueueArn"
{
    "Attributes": {
        "QueueArn": "arn:aws:sqs:us-east-1:473993628677:MyQueue2"
    }
}


步驟 4: 到 SQS 編輯 policy

{
  "Id": "Policy1707705888884",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1707705887802",
      "Action": [
        "sqs:SendMessage"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:sqs:us-east-1:473993628677:MyQueue1",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic"
        }
      },
      "Principal": "*"
    }
  ]
}

{
  "Id": "Policy1707705888884",
  "Version": "2012-10-17",
  "Statement": [
    {
      "Sid": "Stmt1707705887802",
      "Action": [
        "sqs:SendMessage"
      ],
      "Effect": "Allow",
      "Resource": "arn:aws:sqs:us-east-1:473993628677:MyQueue2",
      "Condition": {
        "ArnEquals": {
          "aws:SourceArn": "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic"
        }
      },
      "Principal": "*"
    }
  ]
}


步驟 5: 將 SQS Queue 訂閱到 SNS Topic
[cloudshell-user@ip-10-138-176-84 ~]$ aws sns subscribe --topic-arn "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic" --protocol sqs --notification-endpoint "arn:aws:sqs:us-east-1:473993628677:MyQueue1"
{
    "SubscriptionArn": "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic:de6e8885-824b-4450-99ae-8fc3351870d8"
}
[cloudshell-user@ip-10-138-176-84 ~]$ aws sns subscribe --topic-arn "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic" --protocol sqs --notification-endpoint "arn:aws:sqs:us-east-1:473993628677:MyQueue2"
{
    "SubscriptionArn": "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic:0300ef05-afed-480c-9590-a3797e1dd4dc"
}


步驟 6: 向 SNS Topic 發送 message
[cloudshell-user@ip-10-138-176-84 ~]$ aws sns publish --topic-arn "arn:aws:sns:us-east-1:473993628677:MyFanoutTopic" --message "Hello, fanout world!"
{
    "MessageId": "45c4b5e9-0e8c-56b5-a0ff-ebaa871ffe09"
}


步驟 7: 從 SQS Queue 接收 message
[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs receive-message --queue-url "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue1"
{
    "Messages": [
        {
            "MessageId": "336c2883-0b0b-429c-ada0-c496b40b86ad",
            "ReceiptHandle": "AQEB170H0mtie0ePMmG/g2ZAwS3RZtz1sO7UZO9pEnwHvscXNUsIEBHDh1OY5ekAZeTO6iQsJ8Crlau8DXMzx8UBctfk6w1k9ZpMaoD9x+ykM1t2/wbOksIymRMTbJvpuOSAWemyewXI5aWbIkMyO4oBZ7QSe/CEeV0LQzA+2ddziOZFEmeuCTwZ+eZ3u7GNiei7dB0YZuyKdyp7EJrc/3LZngKj105vUoZGTQbQOBcflWLSB0aofNQTMhjQc2e20zg2SD5tBkkQklX5KZWhv+WCS+nJUuP9VNdw0bGAK4+Hr8SnLbRXfAGsN7zy9cgBd7jydjJJFCULBaCl/8bYGWGHzNWSVIBnCfnStt0ndHDRyjuq7+7dWC9QIK1Zq7KhmDJH",
            "MD5OfBody": "f52631ba39cad6f0e3c0833c106281b0",
            "Body": "{\n  \"Type\" : \"Notification\",\n  \"MessageId\" : \"45c4b5e9-0e8c-56b5-a0ff-ebaa871ffe09\",\n  \"TopicArn\" : \"arn:aws:sns:us-east-1:473993628677:MyFanoutTopic\",\n  \"Message\" : \"Hello, fanout world!\",\n  \"Timestamp\" : \"2024-02-12T02:49:55.386Z\",\n  \"SignatureVersion\" : \"1\",\n  \"Signature\" : \"Ir40tezuo9eSyMDBYnyCzvi5apaKzjsVXC3JinnEYUUN/JkJuB67uYb0RWVbfFLWAGAxMRmTVJ5FOX04ABCpDTcp8b8IlyJ3P09Ekn3wExBmXO4dXyf8VnSLb3D1oFB8FxyqYlb1z1yGJ+bNZIhvcSluJldD/CWGpQVD148rSSdRWEPK8yj89EMlwvUC2t+OTDa58kPnDKdHovdPY7xhfycKCy2yt0Ft2ExOFdFhxTU1ICujKUUbIdVYtRq9LpubgphskfVwq6qYW8dgvr5Ry5Bo2dvjePjK1KqyQYURDmcsnSd1k1cl+N8gOGDbMKP3ooGV0KzCMd52cXXYV3ws3g==\",\n  \"SigningCertURL\" : \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-60eadc530605d63b8e62a523676ef735.pem\",\n  \"UnsubscribeURL\" : \"https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:473993628677:MyFanoutTopic:de6e8885-824b-4450-99ae-8fc3351870d8\"\n}"
        }
    ]
}

[cloudshell-user@ip-10-138-176-84 ~]$ aws sqs receive-message --queue-url "https://sqs.us-east-1.amazonaws.com/473993628677/MyQueue2"
{
    "Messages": [
        {
            "MessageId": "c4e5cef0-5923-4f4f-b045-13df08dc163d",
            "ReceiptHandle": "AQEB5eDDWgy7KmvsxCXF2Yu7t88PlKEZksq47lm9eFoFdfommA8vkrAGN32SuqHXP2f5oZarAybumHGi3/U13nY/3wbOPmbXzRWEi5sTVN2NWhLnPrFLuPAh2DVh8HFQMj9NevNv9IQxn8uI96PgJtZs1NgUiD4w6TutSD0aPoJdNbdaGYcgbbCCUvEPRUcCczcpEhRvFMg+H4ZaeXccFOrEm8ecbNvZINa67/CWyse4gGBKWk//Qz7l38xNBWBPG3e/1HTLqNl0IFG0PhyXqU1CJnBUAaHHpEoK2gvMJVAivcpuOQaBabotwg8KXkKBposfHajPa2ULCVa/8T2F27w2ONgrFPcaCgq+jbFo71PPi3PcVNVP8y4Vke7SKxAAaQTg",
            "MD5OfBody": "6734da73366cc6dd7ca67628bbaba918",
            "Body": "{\n  \"Type\" : \"Notification\",\n  \"MessageId\" : \"45c4b5e9-0e8c-56b5-a0ff-ebaa871ffe09\",\n  \"TopicArn\" : \"arn:aws:sns:us-east-1:473993628677:MyFanoutTopic\",\n  \"Message\" : \"Hello, fanout world!\",\n  \"Timestamp\" : \"2024-02-12T02:49:55.386Z\",\n  \"SignatureVersion\" : \"1\",\n  \"Signature\" : \"Ir40tezuo9eSyMDBYnyCzvi5apaKzjsVXC3JinnEYUUN/JkJuB67uYb0RWVbfFLWAGAxMRmTVJ5FOX04ABCpDTcp8b8IlyJ3P09Ekn3wExBmXO4dXyf8VnSLb3D1oFB8FxyqYlb1z1yGJ+bNZIhvcSluJldD/CWGpQVD148rSSdRWEPK8yj89EMlwvUC2t+OTDa58kPnDKdHovdPY7xhfycKCy2yt0Ft2ExOFdFhxTU1ICujKUUbIdVYtRq9LpubgphskfVwq6qYW8dgvr5Ry5Bo2dvjePjK1KqyQYURDmcsnSd1k1cl+N8gOGDbMKP3ooGV0KzCMd52cXXYV3ws3g==\",\n  \"SigningCertURL\" : \"https://sns.us-east-1.amazonaws.com/SimpleNotificationService-60eadc530605d63b8e62a523676ef735.pem\",\n  \"UnsubscribeURL\" : \"https://sns.us-east-1.amazonaws.com/?Action=Unsubscribe&SubscriptionArn=arn:aws:sns:us-east-1:473993628677:MyFanoutTopic:0300ef05-afed-480c-9590-a3797e1dd4dc\"\n}"
        }
    ]
}

2024/02/11

透過 AWS API Gateway (Rest API) 呼叫 Lambda

設定步驟如下

1.  在 Lambda 撰寫簡單的 Python 程式

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'body': 'Hello from Lambda!'
    }

2. 測試此程式是否如預期正確執行

Test Event Name
my-test

Response
{
  "statusCode": 200,
  "body": "Hello from Lambda!"
}

Function Logs
START RequestId: 131fa0f2-faa0-4ca3-a11d-4c63b6383b1c Version: $LATEST
END RequestId: 131fa0f2-faa0-4ca3-a11d-4c63b6383b1c
REPORT RequestId: 131fa0f2-faa0-4ca3-a11d-4c63b6383b1c	Duration: 1.37 ms	Billed Duration: 2 ms	Memory Size: 128 MB	Max Memory Used: 34 MB

Request ID
131fa0f2-faa0-4ca3-a11d-4c63b6383b1c

3.  至 API Gateway Build Rest API


4. 選擇「New API」、指定「API Name」、click「Create API」


5. click 「Create Resource」


6. 指定 「Resource name」 、click 「Create Resource」


7. create GET method 與指定 Lambda function name (i.e. HelloFunction)



8. Deploy API 與指定 stage name 為 dev



9. 回到原本的 Lambda function,click "Add tirgger"


10. 指定 API Gateway、選擇 "Use existing API"


11. 指定既有 API name (i.e. HelloFunction)、stage 設定為 "dev"、click "Add"


12. 設定成功,並取得 API endpoint



13. 測試成功