Total Pageviews

Showing posts with label AWS. Show all posts
Showing posts with label AWS. Show all posts

2024/06/10

[AWS Cloud Shell Error] eksctl: command not found

Problem

當我透過 CloudShell 執行 eksctl 指令出現以下錯誤訊息

[cloudshell-user@ip-10-138-162-6 ~]$ eksctl create cluster -f cluster.yaml 
-bash: eksctl: command not found


Root Cause

若在執行 eksctl 指令時出現 "command not found" 的錯誤,表示您還未安裝 eksctl

How-To

以下是安裝 eksctl 並解決這個問題的步驟:
以下是安裝 eksctl 並解決這個問題的步驟:
# 下載最新版本的 eksctl
[cloudshell-user@ip-10-138-162-6 ~]$ curl --silent --location "https://github.com/weaveworks/eksctl/releases/latest/download/eksctl_$(uname -s)_amd64.tar.gz" | tar xz -C /tmp

# 將可執行文件移動到 /usr/local/bin
[cloudshell-user@ip-10-138-162-6 ~]$ sudo mv /tmp/eksctl /usr/local/bin

# 驗證安裝
[cloudshell-user@ip-10-138-162-6 ~]$ eksctl version
0.182.0

# 執行結果
[cloudshell-user@ip-10-138-162-6 ~]$ eksctl create cluster -f cluster.yaml 
2024-06-10 06:15:21 []  eksctl version 0.182.0
2024-06-10 06:15:21 []  using region us-east-1
2024-06-10 06:15:21 []  skipping us-east-1e from selection because it doesn't support the following instance type(s): t3.micro
2024-06-10 06:15:21 [ℹ]  setting availability zones to [us-east-1c us-east-1b]
2024-06-10 06:15:21 [ℹ]  subnets for us-east-1c - public:10.0.0.0/19 private:10.0.64.0/19
2024-06-10 06:15:21 [ℹ]  subnets for us-east-1b - public:10.0.32.0/19 private:10.0.96.0/19
2024-06-10 06:15:21 [ℹ]  nodegroup "eks-node-group" will use "ami-0bcb49642ac49d5aa" [AmazonLinux2/1.24]
2024-06-10 06:15:21 [ℹ]  using Kubernetes version 1.24
2024-06-10 06:15:21 [ℹ]  creating EKS cluster "eks-acg" in "us-east-1" region with un-managed nodes
2024-06-10 06:15:21 [ℹ]  1 nodegroup (eks-node-group) was included (based on the include/exclude rules)
2024-06-10 06:15:21 [ℹ]  will create a CloudFormation stack for cluster itself and 1 nodegroup stack(s)
2024-06-10 06:15:21 [ℹ]  will create a CloudFormation stack for cluster itself and 0 managed nodegroup stack(s)
2024-06-10 06:15:21 [ℹ]  if you encounter any issues, check CloudFormation console or try 'eksctl utils describe-stacks --region=us-east-1 --cluster=eks-acg'


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}"
        }
    ]
}