Ngân hàng đề — AWS Certified Developer Associate

Tìm thấy 1356 câu.

Câu 641 AWS Networking & Content Delivery

A Developer has deployed an AWS Lambda function and an Amazon DynamoDB table. The function code returns data from the DynamoDB table when it receives a request. The Developer needs to implement a front end that can receive HTTP GET requests and proxy the request information to the Lambda function.

What is the SIMPLEST and most COST-EFFECTIVE solution?

  1. A

    Implement an API Gateway API with Lambda proxy integration

  2. B

    Implement an Elastic Load Balancer with a Lambda function target

  3. C

    Implement an Amazon Cognito User Pool with a Lambda proxy integration

  4. D

    Implement an API Gateway API with a POST method

Xem giải thích

Đáp án

A — Dựng API Gateway API với Lambda proxy integration.

Vì sao đúng

Đề nêu ba yêu cầu, và chúng cùng chỉ về Lambda proxy integration:

  1. Nhận HTTP GET request
  2. Chuyển tiếp (proxy) thông tin request sang hàm Lambda
  3. Đơn giản nhất và tiết kiệm nhất

Chữ "proxy the request information" trong đề chính là mô tả của Lambda proxy integration: API Gateway đóng gói toàn bộ request thành một sự kiện chuẩn rồi truyền vào hàm:

{
  "httpMethod": "GET",
  "path": "/san-pham/123",
  "queryStringParameters": {"loai": "dien-tu"},
  "headers": {"Authorization": "...", "User-Agent": "..."},
  "pathParameters": {"id": "123"},
  "requestContext": {"identity": {"sourceIp": "203.0.113.5"}},
  "body": null
}

Hàm đọc trực tiếp, không cần mapping template nào:

def lambda_handler(event, context):
    ma_sp = event['pathParameters']['id']
    item = table.get_item(Key={'id': ma_sp})['Item']
    return {
        'statusCode': 200,
        'headers': {'Content-Type': 'application/json'},
        'body': json.dumps(item)
    }

Vì sao tiết kiệm nhất: API Gateway trả tiền theo request, không có gì chạy khi không có ai gọi. Kết hợp với Lambda cũng trả theo lượt chạy, tổng chi phí gần như bằng không khi không có traffic.

Và vì sao đơn giản nhất: proxy integration không cần mapping template — cấu hình gọn hơn hẳn kiểu non-proxy.

Vì sao các phương án khác sai

  • D. API Gateway API với method POST — sai phương thức: đề nói rõ nhận GET request. (Về mặt kỹ thuật thì đây gần đúng nhất trong ba phương án sai, chỉ hỏng ở một chi tiết — đó là loại bẫy kiểm tra xem bạn có đọc kỹ đề không.)
  • B. Elastic Load Balancer với Lambda làm target — ALB gọi được Lambda thật, nhưng nó đắt hơn cho tải thấp: ALB tính phí cố định theo giờ (khoảng 16–18 USD mỗi tháng) kể cả khi không có request nào. API Gateway không có phí cố định. Trượt tiêu chí "COST-EFFECTIVE".
  • C. Cognito User Pool với Lambda proxy integration — sai vai trò dịch vụ: Cognito là thư mục người dùng và cơ chế xác thực, nó không phải cửa ngõ HTTP. Nó không nhận và không định tuyến được request.

Ghi nhớ

So sánh hai cửa ngõ cho Lambda: | | API Gateway | ALB | |---|---|---| | Chi phí | theo request, không phí cố định | phí giờ cố định + LCU | | Điểm hoà vốn | rẻ hơn khi tải thấp tới trung bình | rẻ hơn khi tải rất cao và đều | | Tính năng | throttling, caching, authorizer, usage plan, WAF | định tuyến theo host/path, WAF | | Định dạng sự kiện | httpMethod, pathParameters… | hơi khác |

Hai kiểu tích hợp Lambda trong API Gateway: | | Proxy | Non-proxy (custom) | |---|---|---| | Đầu vào hàm | toàn bộ request theo định dạng chuẩn | do mapping template quyết định | | Đầu ra hàm | phải đúng định dạng (statusCode, headers, body) | mapping template lo | | Mapping template | không dùng | bắt buộc nếu cần biến đổi | | Phổ biến | cách mặc định hiện nay | khi cần biến đổi định dạng |

Với proxy integration, nhớ luôn trả về đúng cấu trúc — thiếu statusCode là API Gateway trả 502 Bad Gateway với thông báo rất mơ hồ.

Và nếu API thật sự đơn giản (không cần cache, không cần usage plan), cân nhắc HTTP API thay vì REST API: nó rẻ hơn khoảng 70% và độ trễ thấp hơn, đổi lại mất một số tính năng như caching và request validation.

Câu 642 AWS Compute

Based on the following AWS CLI command the resulting output, what has happened here?

$ aws lambda invoke --function-name MyFunction --invocation-type Event --payload ewogICJrZXkxIjogInZhbHVlMSIsCiAgImtleTIiOiAidmFsdWUyIiwKICAia2V5MyI6ICJ2YWx1ZTMiCn0= response.json
{
"StatusCode": 202
}
  1. A

    An AWS Lambda function has been invoked asynchronously and has not completed successfully

  2. B

    An AWS Lambda function has been invoked synchronously and has not completed successfully

  3. C

    An AWS Lambda function has been invoked synchronously and has completed successfully

  4. D

    An AWS Lambda function has been invoked asynchronously and has completed successfully

Xem giải thích

Đáp án

D — Hàm Lambda đã được gọi bất đồng bộ và đã hoàn tất thành công (việc tiếp nhận).

Vì sao đúng

Đọc lệnh và kết quả theo hai manh mối:

Manh mối 1 — --invocation-type Event nghĩa là gọi BẤT ĐỒNG BỘ:

RequestResponse → đồng bộ, chờ kết quả
Event           → bất đồng bộ, không chờ    ← lệnh này
DryRun          → chỉ kiểm tra quyền

Manh mối 2 — StatusCode: 202 là mã HTTP 202 Accepted: | Mã | Nghĩa | |---|---| | 200 OK | gọi đồng bộ thành công, kèm kết quả | | 202 Accepted | gọi bất đồng bộ được TIẾP NHẬN thành công | | 204 No Content | DryRun thành công | | 4xx / 5xx | lỗi |

Hai manh mối khớp nhau: gọi bất đồng bộ, và Lambda đã nhận request thành công.

Cần hiểu đúng ý nghĩa của "thành công" ở đây: 202 xác nhận Lambda đã TIẾP NHẬN và xếp sự kiện vào hàng đợi, không xác nhận hàm đã chạy xong hay chạy đúng. Với gọi bất đồng bộ, client không bao giờ biết kết quả — tệp response.json sẽ rỗng.

(Phần --payload là chuỗi base64. Giải mã ra là:

{"key1": "value1", "key2": "value2", "key3": "value3"}

— payload mẫu chuẩn mà AWS hay dùng trong tài liệu.)

Muốn biết hàm có thật sự chạy đúng không thì phải xem CloudWatch Logs hoặc cấu hình destination.

Vì sao các phương án khác sai

  • A. Bất đồng bộ nhưng "chưa hoàn tất thành công" — đúng nửa đầu, sai nửa sau: 202 chính là mã báo tiếp nhận thành công. Nếu có vấn đề, bạn sẽ nhận mã 4xx hoặc 5xx.
  • B và C. "Đồng bộ" — mâu thuẫn với --invocation-type Event. Và với gọi đồng bộ thành công thì mã trả về là 200, không phải 202.

Ghi nhớ

Bảng đối chiếu kiểu gọi và mã trả về — đọc được bảng này là trả lời được mọi câu hỏi dạng này: | Invocation type | Mã thành công | Có kết quả trong response? | |---|---|---| | RequestResponse | 200 | ✅ có | | Event | 202 | ❌ rỗng | | DryRun | 204 | ❌ |

Các mã lỗi thường gặp khi gọi Lambda: | Mã | Nghĩa | |---|---| | 400 | payload không hợp lệ | | 403 | thiếu quyền lambda:InvokeFunction | | 404 | không tìm thấy hàm hoặc alias | | 429 | bị throttle — hết concurrency | | 500 | lỗi trong hàm (chỉ thấy khi gọi đồng bộ) |

Một chi tiết đáng nhớ về gọi đồng bộ: hàm lỗi vẫn trả về StatusCode: 200 — lỗi nằm trong header X-Amz-Function-Error và trong nội dung response, không nằm ở mã HTTP. Nên đừng chỉ kiểm tra StatusCode:

aws lambda invoke --function-name xu-ly response.json
# {"StatusCode": 200, "FunctionError": "Unhandled", "ExecutedVersion": "$LATEST"}

Và với gọi bất đồng bộ, cách duy nhất để biết kết quả là destination hoặc DLQ — luôn cấu hình chúng cho hàm chạy nền quan trọng.

Câu 643 AWS Database

An application is using Amazon DynamoDB as its data store and needs to be able to read 200 items per second as eventually consistent reads. Each item is 12 KB in size.
What value should be set for the table's provisioned throughput for reads?

  1. A

    300 Read Capacity Units

  2. B

    150 Read Capacity Units

  3. C

    600 Read Capacity Units

  4. D

    1200 Read Capacity Units

Xem giải thích

Đáp án

A — 300 Read Capacity Units.

Vì sao đúng

Phép tính RCU gồm ba bước:

Bước 1 — làm tròn LÊN bội số của 4 KB:

Item 12 KB → 12 / 4 = 3 → đã là số nguyên → 3 đơn vị

Bước 2 — nhân với hệ số theo loại đọc: | Loại đọc | Hệ số | |---|---| | Strongly consistent | × 1 | | Eventually consistent | × 0,5 | | Transactional | × 2 |

Đề yêu cầu eventually consistent:

3 đơn vị × 0,5 = 1,5 RCU cho mỗi lần đọc

Bước 3 — nhân với số lần đọc mỗi giây:

1,5 RCU × 200 lần/giây = 300 RCU

Vì sao các phương án khác sai

  • C. 600 — kết quả nếu dùng strongly consistent: 3 × 1 × 200 = 600. Đây là bẫy chính, và nó phát hiện người đọc lướt qua chữ "eventually" trong đề.
  • D. 1200 — kết quả nếu dùng transactional read: 3 × 2 × 200 = 1.200.
  • B. 150 — có thể do chia đôi hai lần, hoặc tính nhầm item là 4 KB thay vì 12 KB.

Ghi nhớ

Hai công thức cần thuộc, và chúng không đối xứng:

RCU — đơn vị 4 KB:

Strongly consistent  : ceil(size / 4 KB)       × số_lần_đọc
Eventually consistent: ceil(size / 4 KB) ÷ 2   × số_lần_đọc
Transactional        : ceil(size / 4 KB) × 2   × số_lần_đọc

WCU — đơn vị 1 KB:

Ghi thường     : ceil(size / 1 KB)       × số_lần_ghi
Transactional  : ceil(size / 1 KB) × 2   × số_lần_ghi

Ba lỗi phổ biến nhất ở dạng bài này:

  1. Nhầm đơn vị — RCU dùng 4 KB, WCU dùng 1 KB.
  2. Quên làm tròn LÊN — item 12,1 KB tốn như item 16 KB (4 đơn vị, không phải 3).
  3. Bỏ qua chữ "strongly" hay "eventually" — nó quyết định nhân 1 hay nhân 0,5.

Áp lại bài này để kiểm tra: 12 KB → 3 đơn vị → eventually nên × 0,5 → 1,5 RCU/lần → 200 lần/giây → 300 RCU.

Thử vài biến thể để nắm chắc công thức: | Kích thước | Loại đọc | Lần/giây | RCU | |---|---|---|---| | 12 KB | eventually | 200 | 300 | | 12 KB | strongly | 200 | 600 | | 13 KB | eventually | 200 | 400 (làm tròn lên 4 đơn vị) | | 4 KB | eventually | 200 | 100 |

Dòng thứ ba minh hoạ điểm quan trọng nhất: lố 1 KB thôi cũng nhảy hẳn một đơn vị, làm chi phí tăng 33%. Trong thiết kế thật, giữ kích thước item sát dưới bội số của 4 KB là tối ưu đáng để ý.

Và nhớ: mặc định của DynamoDB đã là eventually consistent — nhiều ứng dụng bật ConsistentRead=True mà không thực sự cần, rồi trả gấp đôi tiền cho việc đó.

Câu 644 AWS Security, Identity, & Compliance

A Developer is trying to make API calls using AWS SDK. The IAM user credentials used by the application require multi-factor authentication for all API calls.

Which method should the Developer use to access the multi-factor authentication protected API?

  1. A

    GetSessionToken

  2. B

    GetCallerIdentity

  3. C

    GetFederationToken

  4. D

    DecodeAuthorizationMessage

Xem giải thích

Đáp án

A — GetSessionToken.

Vì sao đúng

Yêu cầu rất cụ thể: IAM user bắt buộc dùng MFA cho mọi lời gọi API, và ứng dụng cần gọi API bằng SDK.

sts:GetSessionToken là API duy nhất cho phép IAM user tự lấy credential tạm thời đã kèm chứng thực MFA:

aws sts get-session-token \
  --serial-number arn:aws:iam::123456789012:mfa/lap-trinh-vien \
  --token-code 123456 \
  --duration-seconds 3600

Kết quả là ba giá trị mà SDK dùng để gọi các API tiếp theo:

{
  "Credentials": {
    "AccessKeyId": "ASIA...",
    "SecretAccessKey": "...",
    "SessionToken": "...",
    "Expiration": "2026-08-05T13:00:00Z"
  }
}

Điểm mấu chốt: credential tạm thời này mang aws:MultiFactorAuthPresent = true, nên nó vượt qua được các policy có điều kiện MFA:

{
  "Effect": "Deny",
  "Action": "*",
  "Resource": "*",
  "Condition": {"BoolIfExists": {"aws:MultiFactorAuthPresent": "false"}}
}

Đây là mẫu policy rất phổ biến trong các tổ chức yêu cầu MFA — và nếu ứng dụng dùng thẳng access key dài hạn thì mọi lời gọi đều bị chặn, vì access key không mang thông tin MFA.

Thời hạn: 15 phút đến 36 giờ cho IAM user (mặc định 12 giờ).

Vì sao các phương án khác sai

  • C. GetFederationToken — cũng trả về credential tạm thời, nhưng dành cho liên kết danh tính từ hệ thống bên ngoài: một ứng dụng trung gian dùng credential dài hạn để phát credential cho nhiều người dùng không có tài khoản AWS. Nó không xử lý MFA của chính IAM user gọi nó, và thời hạn tối đa chỉ 36 giờ với các giới hạn khác.
  • B. GetCallerIdentity — chỉ trả lời câu hỏi "tôi đang là ai?" (account ID, ARN, user ID). Rất hữu ích để gỡ lỗi, nhưng không cấp credential nào.
  • D. DecodeAuthorizationMessage — giải mã thông báo lỗi uỷ quyền đã được mã hoá (chuỗi Encoded authorization failure message khi gặp UnauthorizedOperation). Công cụ chẩn đoán, không cấp credential.

Ghi nhớ

Các API của STS và khi nào dùng: | API | Dùng khi | |---|---| | GetSessionToken | IAM user cần credential tạm thời, THƯỜNG KÈM MFA | | AssumeRole | chuyển sang một IAM role (cùng hoặc khác tài khoản) | | AssumeRoleWithWebIdentity | Google, Facebook, Cognito | | AssumeRoleWithSAML | Active Directory, Okta, ADFS | | GetFederationToken | liên kết cho người dùng không có tài khoản AWS | | GetCallerIdentity | "tôi đang là ai?" — lệnh gỡ lỗi hữu ích nhất | | DecodeAuthorizationMessage | giải mã lỗi uỷ quyền |

Phân biệt hai API dễ lẫn: | | GetSessionToken | AssumeRole | |---|---|---| | Đổi danh tính? | ❌ vẫn là chính bạn | ✅ trở thành role | | Quyền | giữ nguyên quyền của user | quyền của role | | Mục đích chính | thêm MFA vào phiên | chuyển vai, chéo tài khoản |

Cách nhớ: GetSessionToken = tôi vẫn là tôi, chỉ có thêm MFA. AssumeRole = tôi hoá thân thành người khác.

Và mẹo thực dụng: thay vì gọi API bằng tay, khai MFA trong ~/.aws/config để AWS CLI tự hỏi mã và tự quản lý credential:

[profile an-toan]
role_arn = arn:aws:iam::123456789012:role/RoleLapTrinhVien
source_profile = default
mfa_serial = arn:aws:iam::123456789012:mfa/lap-trinh-vien
Câu 645 AWS Security, Identity, & Compliance

A Developer received the following error when attempting to launch an Amazon EC2 instance using the AWS CLI.

An error occurred (UnauthorizedOperation) when calling the RunInstances operation: You are not authorized to perform this operation. Encoded authorization failure message: VNVaHFdCohROkbyT_rIXoRyNTp7vXFJCqnGiwPuyKnsSVf-WSSGK_06H3vKnrkUa3qx5D40hqj9HEG8kznr04Acmi6lvc8m51tfqtsomFSDylK15x96ZrxMW7MjDJLrMkM0BasPvy8ixo1wi6X2b0C-J1ThyWU9IcrGd7WbaRDOiGbBhJtKs1z01WSn2rVa5_7sr5PwEK-ARrC9y5Pl54pmeF6wh7QhSv2pFO0y39WVBajL2GmByFmQ4p8s-6Lcgxy23b4NJdJwWOF4QGxK9HcKof1VTVZ2oIpsI-dH6_0t2DI0BTwaIgmaT7ldontI1p7OGz-3wPgXm67x2NVNgaK63zPxjYNbpl32QuXLKUKNlB9DdkSdoLvsuFIvf-lQOXLPHnZKCWMqrkI87eqKHYpYKyV5c11TIZTAJ3MntTGO_TJ4U9ySYvTzU2LgswYOtKF_O76-13fryGG5dhgOW5NxwCWBj6WT2NSJvqOeLykAFjR_ET4lM6Dl1XYfQITWCqIzlvlQdLmHJ1jqjp4gW56VcQCdqozLv2UAg8IdrZIXd0OJ047RQcvvN1IyZN0ElL7dR6RzAAQrftoKMRhZQng6THZs8PZM6wep6-yInzwfg8J5_FW6G_PwYqO-4VunVtJSTzM_F_8kojGlRmzqy7eCk5or__bIisUoslw

What action should the Developer perform to make this error more human-readable?

  1. A

    Make a call to AWS KMS to decode the message

  2. B

    Use the AWS STS decode-authorization-message API to decode the message

  3. C

    Use an open source decoding library to decode the message

  4. D

    Use the AWS IAM decode-authorization-message API to decode this message

Xem giải thích

Đáp án

B — Dùng API sts decode-authorization-message để giải mã thông báo.

Vì sao đúng

Chuỗi dài loằng ngoằng trong thông báo lỗi là thông điệp uỷ quyền đã được mã hoá — AWS cố tình mã hoá nó vì nó chứa chi tiết về policy và tài nguyên mà người gọi có thể không được phép biết.

sts:DecodeAuthorizationMessage giải mã chuỗi đó thành JSON đọc được:

aws sts decode-authorization-message \
  --encoded-message "VNVaHFdCohROkbyT_rIXoRyNTp7vXFJCqnGiwPuyKnsSVf-..." \
  --query DecodedMessage --output text | python3 -m json.tool

Kết quả cho biết chính xác vì sao bị từ chối:

{
  "allowed": false,
  "explicitDeny": false,
  "matchedStatements": {"items": []},
  "failures": {"items": []},
  "context": {
    "principal": {"id": "AIDAI...", "arn": "arn:aws:iam::123456789012:user/lap-trinh-vien"},
    "action": "ec2:RunInstances",
    "resource": "arn:aws:ec2:ap-southeast-1:123456789012:instance/*",
    "conditions": {"items": [...]}
  }
}

Hai trường quan trọng nhất khi đọc kết quả: | Trường | Nghĩa | |---|---| | explicitDeny: true | có một Deny tường minh — tìm trong SCP, boundary, hoặc policy | | matchedStatements rỗng | không có Allow nào khớp — thiếu quyền, phải thêm |

Và quyền để gọi chính API này:

{"Effect": "Allow", "Action": "sts:DecodeAuthorizationMessage", "Resource": "*"}

Vì sao các phương án khác sai

  • D. Dùng API decode-authorization-message của IAM — đây là bẫy chính, và nó chỉ sai tên dịch vụ: API này thuộc về STS, không phải IAM. Lệnh đúng là aws sts decode-authorization-message.
  • A. Gọi AWS KMS để giải mã — KMS không giải mã được chuỗi này. Nó không phải ciphertext của KMS mà là định dạng nội bộ của STS.
  • C. Dùng thư viện giải mã mã nguồn mở — không có thư viện nào làm được: thuật toán và khoá do AWS giữ. Chỉ STS giải mã được.

Ghi nhớ

Quy trình chẩn đoán lỗi UnauthorizedOperation:

1. Sao chép chuỗi sau "Encoded authorization failure message:"
2. aws sts decode-authorization-message --encoded-message "<chuỗi>"
3. Đọc "explicitDeny" và "matchedStatements"
4. Sửa policy tương ứng

Bốn nơi có thể chặn một lời gọi — kiểm tra theo thứ tự này: | Nơi | Dấu hiệu | |---|---| | IAM policy thiếu Allow | matchedStatements rỗng | | Explicit Deny trong IAM policy | explicitDeny: true | | Service Control Policy (SCP) | explicitDeny: true, nhưng không tìm thấy trong IAM | | Permissions boundary | tương tự SCP |

Ba nơi cuối rất hay bị bỏ sót vì chúng không nằm trong policy gắn trực tiếp vào user — người gỡ lỗi tìm mãi trong IAM mà không thấy gì sai.

Các công cụ chẩn đoán quyền khác: | Công cụ | Việc | |---|---| | sts decode-authorization-message | giải mã lỗi cụ thể | | sts get-caller-identity | "tôi đang là ai?" — kiểm tra trước tiên | | iam simulate-principal-policy | mô phỏng: role X có làm được hành động Y không | | IAM Access Analyzer | sinh policy từ log CloudTrail | | CloudTrail | ghi mọi lời gọi bị từ chối kèm lý do |

Mẹo hữu ích nhất: rất nhiều lỗi AccessDenied hoá ra là do đang dùng nhầm profile hoặc nhầm tài khoản — chạy aws sts get-caller-identity trước khi đào sâu vào policy sẽ tiết kiệm rất nhiều thời gian.

Câu 646 AWS Database

A Developer recently created an Amazon DynamoDB table. The table has the following configuration:

The Developer attempted to add two items for userid “user0001” with unique timestamps and received an error for the second item stating: “The conditional request failed”.

What MUST the Developer do to resolve the issue?


  1. A

    Use the SDK to add the items

  2. B

    Update the table with a primary sort key for the timestamp attribute

  3. C

    Recreate the table with a composite key consisting of userid and timestamp

  4. D

    Add a local secondary index (LSI) for the timestamp attribute

Xem giải thích

Đáp án

C — Tạo lại bảng với composite key gồm userid và timestamp.

Vì sao đúng

Ảnh cấu hình bảng cho thấy rõ vấn đề:

Table name:          table1
Primary partition key: userid (String)
Primary sort key:      -            ← KHÔNG CÓ

Bảng chỉ có simple primary key (một partition key duy nhất). Với cấu trúc đó, userid phải là duy nhất — mỗi người dùng chỉ tồn tại đúng một item.

Nên khi thêm item thứ hai cho user0001, DynamoDB từ chối. (Thông báo "The conditional request failed" cho thấy mã đang dùng ConditionExpression: attribute_not_exists(userid) để chống ghi đè — nếu không có điều kiện đó, PutItem sẽ ghi đè im lặng lên item cũ, còn tệ hơn.)

Muốn lưu nhiều bản ghi cho mỗi người dùng, cần composite key:

Partition key: userid      → nhóm các bản ghi theo người dùng
Sort key:      timestamp   → phân biệt các bản ghi trong cùng nhóm

Khi đó tính duy nhất áp cho CẶP (userid, timestamp), nên user0001 có bao nhiêu bản ghi cũng được, miễn khác mốc thời gian.

Và vì sao phải tạo lại bảng: khoá chính của DynamoDB là bất biến. Không có ALTER TABLE, không thêm sort key vào bảng đã tồn tại. Quy trình bắt buộc là:

1. Tạo bảng mới với composite key
2. Di trú dữ liệu (Scan bảng cũ → BatchWriteItem sang bảng mới)
3. Chuyển ứng dụng sang bảng mới
4. Xoá bảng cũ

Sau đó truy vấn rất tự nhiên:

table.query(
    KeyConditionExpression=Key('userid').eq('user0001') &
                           Key('timestamp').between('2026-08-01', '2026-08-31'),
    ScanIndexForward=False        # mới nhất trước
)

Vì sao các phương án khác sai

  • B. "Cập nhật bảng, thêm primary sort key cho thuộc tính timestamp" — đây là bẫy chính: ý tưởng đúng nhưng KHÔNG THỰC HIỆN ĐƯỢC. DynamoDB không cho sửa khoá chính của bảng đã tạo. Từ "update" khiến nó nghe khả thi, nhưng phải là "recreate".
  • D. Thêm local secondary index (LSI) cho timestamp — sai vì hai lẽ. Thứ nhất, LSI chỉ tạo được lúc TẠO BẢNG, không thêm sau được. Thứ hai và quan trọng hơn: index không thay đổi ràng buộc duy nhất của bảng gốc — userid vẫn phải duy nhất, nên vẫn không thêm được item thứ hai.
  • A. Dùng SDK để thêm item — công cụ không phải vấn đề. Console, CLI hay SDK đều gặp cùng ràng buộc, vì nó là quy tắc ở tầng dịch vụ.

Ghi nhớ

Hai loại primary key: | Loại | Thành phần | Tính duy nhất | |---|---|---| | Simple | partition key | partition key phải duy nhất | | Composite | partition key + sort key | CẶP phải duy nhất |

Những gì không đổi được sau khi tạo bảng — đáng thuộc vì chúng quyết định phải thiết kế kỹ từ đầu: | Thuộc tính | Đổi được? | |---|---| | Khoá chính (partition + sort key) | ❌ phải tạo bảng mới | | LSI | ❌ chỉ tạo lúc tạo bảng | | GSI | ✅ thêm và xoá bất cứ lúc nào | | Provisioned capacity | ✅ | | Chế độ billing | ✅ (có giới hạn tần suất) | | Bật Streams, TTL, mã hoá | ✅ |

Đây là khác biệt lớn nhất giữa DynamoDB và CSDL quan hệ: "schema-less" không có nghĩa là không cần thiết kế — ngược lại, bạn phải thiết kế khoá theo mẫu truy vấn ngay từ đầu, vì sửa sau rất tốn kém.

Mẹo hữu ích khi lo hai bản ghi trùng mốc thời gian: dùng sort key ghép:

timestamp#uuid  →  "2026-08-05T10:30:00.123Z#a1b2c3"

Vẫn sắp xếp đúng theo thời gian, mà đảm bảo tuyệt đối không trùng.

Câu 647 AWS Application Integration

A web application is using Amazon Kinesis Data Streams for ingesting IoT data that is then stored before processing for up to 24 hours.
How can the Developer implement encryption at rest for data stored in Amazon Kinesis Data Streams?

  1. A

    Use the Amazon Kinesis Consumer Library (KCL) to encrypt the data

  2. B

    Enable server-side encryption on Kinesis Data Streams with an AWS KMS CMK

  3. C

    Encrypt the data once it is at rest with an AWS Lambda function

  4. D

    Add a certificate and enable SSL/TLS connections to Kinesis Data Streams

Xem giải thích

Đáp án

B — Bật server-side encryption trên Kinesis Data Streams với AWS KMS CMK.

Vì sao đúng

Yêu cầu là mã hoá at-rest cho dữ liệu nằm trong stream (được giữ tới 24 giờ theo đề). Kinesis có sẵn tính năng đó, bật bằng một lời gọi:

aws kinesis start-stream-encryption \
  --stream-name du-lieu-iot \
  --encryption-type KMS \
  --key-id alias/aws/kinesis

Cách nó hoạt động: Kinesis tự mã hoá bản ghi khi ghi vào và tự giải mã khi đọc ra:

Producer → PutRecord → [Kinesis mã hoá bằng KMS] → lưu trữ
                        ← [Kinesis giải mã] ← GetRecords → Consumer

Hoàn toàn trong suốt với ứng dụng — producer và consumer không đổi một dòng mã nào. Thứ duy nhất phải thêm là quyền KMS:

{"Effect": "Allow",
 "Action": ["kms:GenerateDataKey", "kms:Decrypt"],
 "Resource": "arn:aws:kms:...:key/abc-123"}

Hai lựa chọn khoá: | Khoá | Đặc điểm | |---|---| | aws/kinesis (AWS managed) | miễn phí quản lý, đơn giản nhất | | CMK riêng | kiểm soát key policy, vô hiệu hoá được, có vết CloudTrail |

Vì sao các phương án khác sai

  • D. Thêm chứng chỉ và bật SSL/TLS cho kết nối tới Kinesis — nhầm hai loại mã hoá: TLS bảo vệ dữ liệu khi truyền (in transit), còn đề hỏi về khi lưu (at rest). (Và mọi endpoint của Kinesis vốn đã là HTTPS — không có gì để bật.)
  • A. Dùng Kinesis Consumer Library (KCL) để mã hoá dữ liệu — sai thời điểm: KCL chạy ở phía consumer, tức là sau khi dữ liệu đã nằm trong stream. Nó không thể mã hoá thứ đã được lưu.
  • C. Dùng Lambda mã hoá dữ liệu sau khi nó đã ở trạng thái lưu trữ — không làm được: một khi bản ghi đã vào stream, bạn không sửa được nó tại chỗ. Kinesis là kho append-only.

Ghi nhớ

Bảo mật cho Kinesis Data Streams: | Lớp | Cơ chế | |---|---| | At rest | SSE với KMS — bật một thiết lập | | In transit | HTTPS — mặc định, luôn bật | | Truy cập | IAM policy cho stream | | Mạng riêng | VPC interface endpoint (PrivateLink) |

Ba lưu ý về SSE của Kinesis:

  1. Bật hoặc tắt mã hoá không ảnh hưởng dữ liệu đã có — chỉ áp cho bản ghi mới. Sau khi bật, dữ liệu cũ trong stream vẫn ở dạng chưa mã hoá cho tới khi hết hạn giữ.
  2. Có phí KMS API cho mỗi thao tác mã hoá và giải mã. Với thông lượng rất cao, khoản này đáng tính vào chi phí.
  3. Producer và consumer đều cần quyền KMS — thiếu ở một phía là gặp AccessDeniedException khá khó hiểu, vì lỗi trông như vấn đề của Kinesis chứ không phải của KMS.

Nguyên tắc chung rất đáng nhớ, áp cho nhiều dịch vụ: "mã hoá mà không sửa mã ứng dụng" ⇒ server-side encryption. Điều này đúng với Kinesis, S3, SQS, SNS, EBS, RDS và DynamoDB.

Ngược lại, nếu đề nói "dữ liệu phải được mã hoá TRƯỚC KHI gửi tới dịch vụ" hoặc "AWS không được thấy bản rõ" thì mới cần client-side encryption — và khi đó bạn phải tự dùng kms:GenerateDataKey cùng envelope encryption.

Câu 648 AWS Compute

A Developer has updated an AWS Lambda function and published a new version. To ensure the code is working as expected the Developer needs to initially direct a percentage of traffic to the new version and gradually increase this over time. It is important to be able to rollback if there are any issues reported.

What is the BEST way the Developer can implement the migration to the new version SAFELY?

  1. A

    Create an Alias, assign the current and new versions and use traffic shifting to assign a percentage of traffic to the new version

  2. B

    Use an Amazon Elastic Load Balancer to direct a percentage of traffic to each target group containing the Lambda function versions

  3. C

    Use an immutable update with a new ASG to deploy the new version in parallel, following testing cutover to the new version

  4. D

    Create an Amazon Route 53 weighted routing policy pointing to the current and new versions, assign a lower weight to the new version

Xem giải thích

Đáp án

A — Tạo alias, gán version hiện tại và version mới, dùng traffic shifting để chuyển dần phần trăm traffic sang version mới.

Vì sao đúng

Lambda alias có tính năng weighted routing dựng sẵn cho đúng nhu cầu này — chuyển dần traffic giữa hai version:

# Ban đầu: alias "prod" trỏ 100% vào version 4
# Chuyển 10% sang version 5
aws lambda update-alias --function-name xu-ly --name prod \
  --function-version 5 \
  --routing-config '{"AdditionalVersionWeights": {"4": 0.9}}'

Đọc cấu hình này: version 5 là chính, nhưng 90% traffic vẫn về version 4 — tức là 10% sang bản mới.

Tăng dần theo thời gian, và rollback là đặt lại về 0:

# Tăng lên 50%
aws lambda update-alias --function-name xu-ly --name prod \
  --function-version 5 --routing-config '{"AdditionalVersionWeights": {"4": 0.5}}'

# Hài lòng → chuyển hết
aws lambda update-alias --function-name xu-ly --name prod --function-version 5

# Có vấn đề → rollback TỨC THÌ
aws lambda update-alias --function-name xu-ly --name prod --function-version 4

Vì sao đây là cách "SAFELY": rollback chỉ là một lời gọi API, có hiệu lực trong vài giây — không phải triển khai lại gì, và version cũ vẫn nguyên vẹn ở đó.

Điểm quan trọng về kiến trúc: mọi thứ gọi hàm đều trỏ vào alias, không trỏ vào version. Nên API Gateway, event source, và quyền đều không cần đụng tới khi bạn chuyển traffic.

(Muốn tự động hoá hoàn toàn, dùng CodeDeploy với deployment preference — nó chuyển traffic theo lịch canary hoặc linear và tự rollback khi CloudWatch alarm kêu.)

Vì sao các phương án khác sai

  • B. Dùng ELB chia traffic giữa các target group chứa các version Lambda — ALB không phân biệt được version Lambda: một target group Lambda trỏ tới một hàm hoặc một alias, và bạn không dùng nó để chia phần trăm giữa hai version của cùng một hàm. Cách đúng vẫn là alias.
  • C. Immutable update với ASG mới — khái niệm của EC2 và Elastic Beanstalk. Lambda không có Auto Scaling group — nó tự co giãn hoàn toàn.
  • D. Route 53 weighted routing trỏ tới hai version — Route 53 định tuyến theo DNS tới endpoint mạng, mà Lambda version không có endpoint DNS riêng. Ngoài ra chuyển traffic bằng DNS còn phụ thuộc TTL, nên rollback không tức thì.

Ghi nhớ

Khái niệm Là gì Đổi được?
$LATEST bản đang sửa ✅ (đừng trỏ production vào đây)
Version bản chụp BẤT BIẾN ❌
Alias con trỏ có tên tới một hoặc HAI version ✅

Mẫu thực hành tốt:

$LATEST                    ← nơi phát triển
version 1, 2, 3, 4, 5      ← bất biến
alias "dev"   → $LATEST
alias "test"  → version 5
alias "prod"  → version 4 (90%) + version 5 (10%)   ← đang canary

Ba lưu ý khi dùng traffic shifting:

  1. Chỉ chia được giữa ĐÚNG HAI version — không phải ba trở lên.
  2. Không dùng được với $LATEST — cả hai đầu phải là version đã publish.
  3. Cấp quyền cho alias, không phải cho hàm chung chung — thiếu qualifier là API Gateway trả 500 không nói gì:
    aws lambda add-permission --function-name xu-ly --qualifier prod \
      --statement-id ApiGatewayInvoke --action lambda:InvokeFunction \
      --principal apigateway.amazonaws.com
    

Và nhớ: CloudWatch metric tách riêng theo version, nên bạn so sánh được tỷ lệ lỗi và độ trễ giữa bản cũ và bản mới trong lúc canary — đó là dữ liệu để quyết định tăng tỷ lệ hay rollback.

Câu 649 Chọn nhiều đáp án AWS Compute

A company is migrating a stateful web service into the AWS cloud. The objective is to refactor the application to realize the benefits of cloud computing. How can the Developer leading the project refactor the application to enable more elasticity? (Select TWO.)

  1. A

    Use Amazon CloudFormation and the Serverless Application Model

  2. B

    Use Amazon CloudFront with a Web Application Firewall

  3. C

    Store the session state in an Amazon DynamoDB table

  4. D

    Use an Elastic Load Balancer and Auto Scaling Group

  5. E

    Store the session state in an Amazon RDS database

Xem giải thích

Đáp án

C và D.

  • C — Lưu session state trong bảng DynamoDB
  • D — Dùng Elastic Load Balancer và Auto Scaling group

Vì sao đúng

Đề nói ứng dụng đang có trạng thái (stateful), và mục tiêu là tăng độ đàn hồi (elasticity). Hai việc này phải làm cùng nhau — đó là lý do câu hỏi chọn hai đáp án.

C — tách trạng thái ra ngoài, để tầng web trở nên phi trạng thái. Đây là điều kiện tiên quyết: nếu session còn nằm trong bộ nhớ của từng instance thì mở rộng ngang không hoạt động đúng — instance mới không có session, và instance bị thu hồi làm mất session.

table.put_item(Item={
    'session_id': sid,
    'du_lieu': du_lieu,
    'het_han': int(time.time()) + 3600     # TTL tự dọn
})

D — thêm cơ chế co giãn. Sau khi tầng web phi trạng thái, ALB và ASG mới phát huy tác dụng: request rơi vào instance nào cũng được phục vụ đúng, và ASG thêm/bớt máy theo tải mà không ai bị đăng xuất.

Client → ALB → EC2 #1, #2, #3… (phi trạng thái, ASG quản lý số lượng)
                  ↓
             DynamoDB (session dùng chung)

Hai đáp án này bổ sung cho nhau: C làm cho D khả thi.

Vì sao các phương án khác sai

  • E. Lưu session state trong CSDL Amazon RDS — về nguyên tắc thì tách được trạng thái ra ngoài, nhưng nó kém hơn DynamoDB rõ rệt cho mục đích này: độ trễ cao hơn, và session bị đọc ở mọi request nên áp lực rất lớn. RDS cũng không có TTL (phải tự viết job dọn) và không co giãn ngang dễ như DynamoDB.
  • B. CloudFront với Web Application Firewall — CDN cải thiện độ trễ cho nội dung tĩnh và WAF lọc traffic độc hại. Cả hai đều hữu ích, nhưng không giải quyết vấn đề trạng thái và không làm tầng ứng dụng co giãn.
  • A. CloudFormation và Serverless Application Model — công cụ hạ tầng dưới dạng mã. Chúng giúp triển khai nhất quán và lặp lại được, nhưng bản thân việc dùng CloudFormation không làm ứng dụng đàn hồi hơn — bạn vẫn có thể dùng nó để triển khai một ứng dụng stateful không co giãn.

Ghi nhớ

Ba trụ cột của kiến trúc web đàn hồi: | Trụ cột | Thành phần | |---|---| | Tầng tính toán phi trạng thái | đưa session ra kho ngoài | | Phân phối tải | ALB / NLB | | Co giãn tự động | Auto Scaling group |

Thứ tự rất quan trọng: trụ cột đầu tiên là điều kiện cho hai trụ cột sau.

Các lựa chọn lưu session ngoài: | Kho | Độ trễ | Bền | Chọn khi | |---|---|---|---| | ElastiCache Redis | thấp nhất | vừa | cần nhanh nhất | | DynamoDB | mili giây | rất bền, đa AZ | cần bền, có TTL, không quản lý | | RDS | cao hơn | bền | quá nặng cho session |

Ba thứ không bao giờ dùng làm kho session: | Không dùng | Vì sao | |---|---| | Bộ nhớ hoặc ổ đĩa cục bộ | mất khi instance được thay | | Instance store | mất khi instance dừng | | Sticky session làm giải pháp duy nhất | instance hỏng là mất session |

Nhận dạng nhanh trong đề: thấy chữ "stateful" kèm yêu cầu "elasticity" hay "scale" ⇒ đáp án gần như luôn gồm tách session ra ngoài cộng với ALB + ASG.

Và sau khi làm hai việc này, bước tiếp theo tự nhiên là health check kiểu ELB cho ASG — để instance có ứng dụng chết (chứ không chỉ máy chết) cũng được thay thế.

Câu 650 AWS Security, Identity, & Compliance

A development team are creating a mobile application that customers will use to receive notifications and special offers. Users will not be required to log in.

What is the MOST efficient method to grant users access to AWS resources?

  1. A

    Use Amazon Cognito Federated Identities and setup authentication using a Cognito User Pool

  2. B

    Use Amazon Cognito to associate unauthenticated users with an IAM role that has limited access to resources

  3. C

    Use an IAM SAML 2.0 identity provider to establish trust

  4. D

    Embed access keys in the application that have limited access to resources

Xem giải thích

Đáp án

B — Dùng Amazon Cognito gắn người dùng chưa xác thực (unauthenticated) với một IAM role có quyền hạn chế.

Vì sao đúng

Đề có một dữ kiện quyết định: người dùng KHÔNG phải đăng nhập. Vậy mà ứng dụng vẫn cần truy cập tài nguyên AWS (nhận thông báo, lấy ưu đãi).

Cognito identity pool có sẵn cơ chế cho tình huống này — unauthenticated identities:

Ứng dụng mở lên (không ai đăng nhập)
        ↓
  Identity Pool cấp identity ID cho thiết bị đó
        ↓ sts:AssumeRoleWithWebIdentity
  Credential AWS TẠM THỜI với quyền của UNAUTHENTICATED ROLE
        ↓
  Gọi SNS, S3, DynamoDB trong phạm vi cho phép
// Không có 'logins' — nghĩa là người dùng khách
const credentials = fromCognitoIdentityPool({
  identityPoolId: 'ap-southeast-1:xxxx-xxxx'
});

Identity pool có hai role riêng biệt, và bạn cấu hình quyền khác nhau cho mỗi loại: | Role | Cho ai | Quyền | |---|---|---| | Unauthenticated | người dùng khách | tối thiểu — chỉ đọc nội dung công khai | | Authenticated | người đã đăng nhập | rộng hơn |

Ví dụ policy cho role khách:

{
  "Effect": "Allow",
  "Action": ["s3:GetObject"],
  "Resource": "arn:aws:s3:::noi-dung-cong-khai/uu-dai/*"
}

Điểm hay: credential là tạm thời và tự hết hạn, và bạn vẫn theo dõi được từng thiết bị qua identity ID — hữu ích khi sau này người dùng quyết định đăng ký, bạn gộp được dữ liệu của họ.

Vì sao các phương án khác sai

  • A. Dùng Cognito Federated Identities với xác thực qua user pool — mâu thuẫn với đề: user pool là cơ chế đăng ký và đăng nhập, mà đề nói rõ người dùng sẽ KHÔNG đăng nhập. Thiết lập user pool ở đây là thừa và không dùng tới.
  • C. Dùng IAM SAML 2.0 identity provider — SAML dành cho danh tính doanh nghiệp (Active Directory, Okta). Người dùng ứng dụng di động công khai không có danh tính SAML nào, và cũng không có gì để thiết lập quan hệ tin cậy.
  • D. Nhúng access key vào ứng dụng — sai lầm bảo mật nghiêm trọng nhất: mã ứng dụng di động giải nén và đọc được (chỉ cần mở file APK hoặc IPA). Access key dài hạn nằm trong đó là bị lộ hoàn toàn, và thu hồi thì phải cập nhật ứng dụng cho mọi người dùng.

Ghi nhớ

User Pool Identity Pool
Là gì thư mục người dùng bộ đổi danh tính lấy credential AWS
Phát ra JWT credential AWS tạm thời
Người dùng khách ❌ ✅ unauthenticated role
Gọi thẳng S3/DynamoDB/SNS ❌ ✅

Cách chọn: | Đề nói | Chọn | |---|---| | "users will not log in", "guest access" | identity pool với unauthenticated role | | "đăng ký, đăng nhập, quản lý người dùng" | user pool | | cả hai nhu cầu | dùng cả hai |

Cảnh báo quan trọng về unauthenticated role: nó cấp credential cho bất kỳ ai trên Internet — chỉ cần biết identity pool ID (vốn nằm trong mã ứng dụng). Nên:

  1. Giữ quyền ở mức tối thiểu tuyệt đối — chỉ đọc, chỉ đúng tài nguyên công khai.
  2. Không cấp quyền ghi trừ khi thật sự cần và có kiểm soát chặt.
  3. Tắt hẳn unauthenticated access nếu ứng dụng không cần chế độ khách.

Và một tính năng hữu ích khi khách quyết định đăng ký: MergeDeveloperIdentities hoặc việc thêm logins vào cùng identity ID cho phép giữ lại dữ liệu mà họ đã tạo trong lúc dùng chế độ khách.