Ngân hàng đề — AWS Certified Developer Associate
Tìm thấy 1356 câu.
A company is running a web application on Amazon EC2 behind an Elastic Load Balancer (ELB). The company is concerned about the security of the web application and would like to secure the application with SSL certificates. The solution should not have any performance impact on the EC2 instances.
What steps should be taken to secure the web application? (Select TWO.)
-
A
Install SSL certificates on the EC2 instances
-
B
Configure the Elastic Load Balancer for SSL termination
-
C
Add an SSL certificate to the Elastic Load Balancer
-
D
Configure the Elastic Load Balancer with SSL passthrough
-
E
Configure Server-Side Encryption with KMS managed keys
Xem giải thích
Đáp án
B và C.
- C — Thêm chứng chỉ SSL vào Elastic Load Balancer
- B — Cấu hình ELB làm SSL termination
Vì sao đúng
Ràng buộc quyết định nằm ở câu cuối của đề: giải pháp không được ảnh hưởng tới hiệu năng của EC2 instance.
SSL termination tại load balancer làm đúng điều đó — toàn bộ công việc mã hoá và giải mã diễn ra trên ELB, không phải trên instance:
Client ──HTTPS (ELB giải mã ở đây)──→ ELB ──HTTP──→ EC2 (không tốn CPU cho TLS)
Bắt tay TLS là thao tác tốn CPU đáng kể (nhất là phần bất đối xứng lúc khởi tạo kết nối). Đẩy nó sang ELB nghĩa là EC2 dành trọn CPU cho việc xử lý ứng dụng.
Hai bước cấu hình chính là hai đáp án:
# C — gắn chứng chỉ (lấy từ ACM, miễn phí và tự gia hạn)
# B — tạo listener HTTPS ở phía trước, chuyển tiếp HTTP xuống target group
aws elbv2 create-listener \
--load-balancer-arn arn:aws:elasticloadbalancing:...:loadbalancer/app/web/abc \
--protocol HTTPS --port 443 \
--certificates CertificateArn=arn:aws:acm:...:certificate/xyz \
--ssl-policy ELBSecurityPolicy-TLS13-1-2-2021-06 \
--default-actions Type=forward,TargetGroupArn=<target-group-HTTP>
Lợi ích kèm theo: quản lý chứng chỉ tập trung ở một chỗ thay vì cài lên từng instance, và chứng chỉ ACM tự gia hạn vĩnh viễn.
Vì sao các phương án khác sai
- A. Cài chứng chỉ SSL lên các EC2 instance — vi phạm thẳng ràng buộc của đề: instance phải tự xử lý TLS, tốn CPU. Ngoài ra bạn phải cài và gia hạn chứng chỉ trên từng máy — và với Auto Scaling, mọi instance mới đều cần bước đó.
- D. Cấu hình ELB với SSL passthrough — passthrough chuyển tiếp traffic đã mã hoá xuống instance nguyên vẹn, nên instance vẫn phải giải mã — cùng vấn đề với A. (Và với ALB thì không làm được: ALB hoạt động ở tầng 7 nên bắt buộc phải giải mã để đọc HTTP. Passthrough chỉ có ở NLB, vốn ở tầng 4.)
- E. Cấu hình Server-Side Encryption với khoá KMS — nhầm hai loại mã hoá: SSE bảo vệ dữ liệu khi nằm yên trên đĩa (at rest), còn đề hỏi về mã hoá khi truyền (in transit). Hoàn toàn khác nhau.
Ghi nhớ
Ba mô hình mã hoá với load balancer: | Mô hình | Client → ELB | ELB → EC2 | CPU của EC2 | |---|---|---|---| | SSL termination | HTTPS | HTTP | không tốn | | End-to-end encryption | HTTPS | HTTPS | tốn | | SSL passthrough (chỉ NLB) | HTTPS | HTTPS nguyên vẹn | tốn |
Cách chọn:
- "không ảnh hưởng hiệu năng EC2" ⇒ termination
- "tuân thủ đòi mã hoá toàn tuyến" ⇒ end-to-end
- "ELB không được thấy nội dung" ⇒ passthrough với NLB
Với end-to-end, có một chi tiết tiện lợi: ALB không kiểm tra chứng chỉ của backend, nên EC2 dùng được chứng chỉ tự ký — không tốn thêm chi phí nào.
Vài lưu ý về chứng chỉ: | Điểm | Chi tiết | |---|---| | ACM công cộng | miễn phí, tự gia hạn với DNS validation | | Không xuất được private key | nên không cài lên EC2 được — chỉ dùng với ELB, CloudFront, API Gateway | | SNI | ALB gắn được nhiều chứng chỉ trên một listener | | SSL policy | chọn bản mới (TLS13-1-2-...) — bản cũ vẫn cho phép TLS 1.0/1.1 |
Và nhớ bật X-Forwarded-Proto khi dùng termination: thiếu nó, ứng dụng tưởng client đang dùng HTTP và có thể sinh ra link sai giao thức hoặc lặp vô hạn khi tự chuyển hướng sang HTTPS.
A customer requires a schema-less, key/value database that can be used for storing customer orders. Which type of AWS database is BEST suited to this requirement?
-
A
Amazon DynamoDB
-
B
Amazon S3
-
C
Amazon ElastiCache
-
D
Amazon RDS
Xem giải thích
Đáp án
A — Amazon DynamoDB.
Vì sao đúng
Đề nêu ba yêu cầu, và DynamoDB khớp cả ba:
- Schema-less (không có lược đồ cố định)
- Khoá–giá trị (key/value)
- Lưu đơn hàng của khách
DynamoDB là CSDL NoSQL khoá–giá trị và tài liệu, nơi mỗi item có thể có tập thuộc tính khác nhau — chỉ khoá chính là bắt buộc:
table.put_item(Item={
'don_hang_id': 'DH-001', # khoá chính — bắt buộc
'khach_hang': 'Nguyễn Văn A',
'tong_tien': 500000,
'ghi_chu': 'Giao giờ hành chính' # item khác có thể không có trường này
})
table.put_item(Item={
'don_hang_id': 'DH-002',
'khach_hang': 'Trần Thị B',
'tong_tien': 1200000,
'ma_giam_gia': 'SALE20', # trường chỉ có ở item này
'dia_chi_phu': {...} # cấu trúc lồng nhau cũng được
})
Không cần ALTER TABLE, không cần di trú lược đồ — thêm trường mới là chuyện của ứng dụng.
Các đặc điểm khác khiến nó hợp với dữ liệu đơn hàng: | Đặc điểm | Chi tiết | |---|---| | Độ trễ | mili giây một chữ số, ổn định ở mọi quy mô | | Co giãn | on-demand hoặc auto scaling, không giới hạn dung lượng | | Bền vững | nhân bản trên 3 AZ | | TTL | tự xoá dữ liệu hết hạn | | Streams | phản ứng ngay khi có đơn hàng mới |
Vì sao các phương án khác sai
- D. Amazon RDS — CSDL quan hệ, có lược đồ cố định: mỗi bảng có tập cột xác định, thêm cột phải chạy
ALTER TABLE. Trái hẳn yêu cầu "schema-less". - C. Amazon ElastiCache — kho khoá–giá trị trong bộ nhớ, đúng một nửa yêu cầu. Nhưng nó là cache, không phải CSDL bền vững: dữ liệu có thể mất khi node hỏng, và nó không được thiết kế làm nguồn dữ liệu chính. Đơn hàng của khách không thể để ở đó.
- B. Amazon S3 — kho object, không phải CSDL khoá–giá trị. Nó không hỗ trợ truy vấn theo thuộc tính, không có index, không có cập nhật một phần. Muốn tìm "đơn hàng của khách X" thì phải quét toàn bộ hoặc tự dựng chỉ mục riêng.
Ghi nhớ
Chọn CSDL theo nhu cầu — bảng này đáng thuộc: | Nhu cầu | Dịch vụ | |---|---| | NoSQL khoá–giá trị, schema-less, độ trễ mili giây | DynamoDB | | Quan hệ, có lược đồ, JOIN, transaction phức tạp | RDS / Aurora | | Cache trong bộ nhớ | ElastiCache | | Kho object, tệp lớn | S3 | | Kho dữ liệu phân tích (OLAP) | Redshift | | Đồ thị, quan hệ nhiều bậc | Neptune | | Chuỗi thời gian | Timestream | | Sổ cái bất biến, có xác minh mật mã | QLDB | | Tương thích MongoDB | DocumentDB |
Nhận dạng nhanh trong đề: "schema-less", "key/value", "NoSQL", "single-digit millisecond" ⇒ DynamoDB.
Một lưu ý thiết kế quan trọng khi dùng DynamoDB cho đơn hàng: "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ì DynamoDB không JOIN được và đổi khoá chính sau này là phải tạo bảng mới.
Ví dụ khoá hợp lý cho đơn hàng:
Partition key: khach_hang_id
Sort key: ngay_dat#don_hang_id
Cấu trúc này trả lời tốt câu hỏi phổ biến nhất — "các đơn hàng gần đây của khách X" — bằng một Query duy nhất. Muốn tra theo mã đơn hàng thì thêm một GSI.
An application developer is crafting a new software product. To streamline the registration process, they want new users to be able to set up their accounts using their existing social media profiles.
Which AWS service or feature would be the most appropriate for achieving this goal?
-
A
Amazon Cognito User Pools
-
B
AWS Managed Microsoft AD
-
C
AWS Security Token Service
-
D
AWS Identity and Access Management (IAM)
Xem giải thích
Đáp án
A — Amazon Cognito User Pools.
Vì sao đúng
Yêu cầu: cho phép người dùng đăng ký bằng tài khoản mạng xã hội có sẵn — đây gọi là social identity federation, và Cognito user pool hỗ trợ sẵn.
Cấu hình chỉ là khai identity provider:
aws cognito-idp create-identity-provider \
--user-pool-id ap-southeast-1_xxx \
--provider-name Google \
--provider-type Google \
--provider-details client_id=xxx.apps.googleusercontent.com,client_secret=yyy,authorize_scopes="email profile openid" \
--attribute-mapping email=email,name=name
Các nhà cung cấp được hỗ trợ sẵn: | Nhà cung cấp | Kiểu | |---|---| | Google, Facebook, Amazon, Apple | social | | SAML 2.0 | doanh nghiệp (Okta, ADFS, Azure AD) | | OpenID Connect | bất kỳ IdP nào theo chuẩn OIDC |
Điểm hay của user pool là nó hợp nhất mọi nguồn danh tính thành một thư mục duy nhất:
Đăng ký bằng email/mật khẩu ─┐
Đăng nhập bằng Google ───────┼→ USER POOL → cùng một JWT, cùng một hồ sơ
Đăng nhập bằng Facebook ─────┘
Ứng dụng chỉ làm việc với một loại token duy nhất, không cần biết người dùng đến từ đâu. Và attribute mapping đưa email, tên, ảnh đại diện từ nhà cung cấp vào hồ sơ Cognito.
Với hosted UI, toàn bộ luồng OAuth có sẵn giao diện — bạn không phải viết một dòng mã xác thực nào.
Vì sao các phương án khác sai
- D. AWS IAM — quản lý danh tính của nhân sự và ứng dụng trong AWS, không phải người dùng cuối. Nó không liên kết được với Google hay Facebook, và có giới hạn 5.000 IAM user mỗi tài khoản — không dùng cho ứng dụng có người dùng công khai.
- C. AWS STS — dịch vụ cấp credential AWS tạm thời. Nó là thành phần bên dưới mà Cognito identity pool gọi tới (
AssumeRoleWithWebIdentity), nhưng bản thân nó không quản lý người dùng, không có đăng ký, không có hồ sơ. - B. AWS Managed Microsoft AD — thư mục doanh nghiệp (Active Directory) cho nhân viên nội bộ. Nó không liên kết với mạng xã hội và không dành cho người dùng công khai.
Ghi nhớ
| User Pool | Identity Pool | |
|---|---|---|
| Là gì | thư mục người dùng | bộ đổi danh tính lấy credential AWS |
| Social login | ✅ | ✅ (nhưng không lưu người dùng) |
| Đăng ký, đặt lại mật khẩu, MFA | ✅ | ❌ |
| Phát ra | JWT | credential AWS tạm thời |
Cách chọn:
- "đăng ký, đăng nhập, social login" ⇒ user pool ← câu này
- "truy cập thẳng S3/DynamoDB" ⇒ identity pool
- cả hai nhu cầu ⇒ dùng cả hai
Ba việc cần làm khi cấu hình social login:
- Đăng ký ứng dụng ở phía nhà cung cấp (Google Cloud Console, Facebook Developers…) để lấy client ID và secret.
- Khai callback URL trong cả hai phía — sai URL là lỗi phổ biến nhất, và thông báo lỗi thường rất mơ hồ.
- Ánh xạ thuộc tính để email và tên từ nhà cung cấp vào đúng trường của user pool.
Và một điểm thực dụng: nếu cùng một người đăng ký bằng email rồi sau đó đăng nhập bằng Google với cùng email đó, Cognito mặc định coi là hai người dùng khác nhau. Muốn gộp lại thì dùng API AdminLinkProviderForUser.
A company wants to implement authentication for its new REST service using Amazon API Gateway. To authenticate the calls, each request must include HTTP headers with a client ID and user ID. These credentials must be compared to authentication data in an Amazon DynamoDB table.
What MUST the company do to implement this authentication in API Gateway?
-
A
Implement an AWS Lambda authorizer that references the DynamoDB authentication table
-
B
Implement an Amazon Cognito authorizer that references the DynamoDB authentication table
-
C
Modify the integration requests to require the credentials, then grant API Gateway access to the authentication table
-
D
Create a model that requires the credentials, then grant API Gateway access to the authentication table
Xem giải thích
Đáp án
A — Cài đặt một Lambda authorizer tham chiếu tới bảng xác thực trong DynamoDB.
Vì sao đúng
Yêu cầu rất đặc thù: xác thực dựa trên header HTTP tuỳ chỉnh (client ID và user ID), đối chiếu với bảng DynamoDB của riêng công ty.
Đó là logic tuỳ ý, và Lambda authorizer là điểm mở rộng duy nhất của API Gateway cho việc đó:
def handler(event, context):
client_id = event['headers'].get('client-id')
user_id = event['headers'].get('user-id')
item = table.get_item(Key={'client_id': client_id, 'user_id': user_id}).get('Item')
if not item or not item.get('con_hieu_luc'):
raise Exception('Unauthorized') # → 401
return {
'principalId': user_id,
'policyDocument': {
'Version': '2012-10-17',
'Statement': [{'Action': 'execute-api:Invoke',
'Effect': 'Allow', 'Resource': event['methodArn']}]},
'context': {'vaiTro': item['vai_tro']} # truyền tiếp xuống backend
}
Vì đề nói xác thực dựa trên nhiều header, phải dùng authorizer kiểu REQUEST (nhận toàn bộ header, query string, path), không phải kiểu TOKEN (chỉ nhận một header).
Kết quả được cache (mặc định 300 giây), nên không phải gọi hàm và truy vấn DynamoDB ở mọi request.
Vì sao các phương án khác sai
- B. Cognito authorizer tham chiếu bảng DynamoDB — Cognito không đọc bảng DynamoDB của bạn. Nó có thư mục người dùng riêng; dùng Cognito nghĩa là di trú toàn bộ dữ liệu người dùng sang đó, không phải đối chiếu với bảng có sẵn.
- D. Tạo Model yêu cầu credential rồi cấp cho API Gateway quyền vào bảng — hiểu sai chức năng: Model là JSON Schema mô tả cấu trúc request/response, dùng để kiểm tra tính hợp lệ của payload và sinh SDK. Nó không xác thực và không truy vấn được CSDL.
- C. Sửa integration request để yêu cầu credential rồi cấp quyền cho API Gateway — integration request chỉ biến đổi và chuyển tiếp request tới backend. Nó không có logic so sánh hay quyết định cho phép/từ chối.
Ghi nhớ
Bốn cơ chế uỷ quyền của API Gateway: | Cơ chế | Dùng khi | |---|---| | Lambda authorizer | logic tuỳ ý — header riêng, CSDL riêng, IdP bên thứ ba | | Cognito user pool | dùng thư mục người dùng của AWS | | IAM (SigV4) | client có danh tính AWS | | JWT authorizer (HTTP API) | OIDC/OAuth2 chuẩn |
Hai kiểu Lambda authorizer: | Kiểu | Đầu vào | |---|---| | TOKEN | một header (thường là Authorization) | | REQUEST | toàn bộ header, query, path, stage variable |
Nhận dạng nhanh: đề nêu nhiều header tuỳ chỉnh hoặc nguồn dữ liệu xác thực của riêng bạn ⇒ Lambda authorizer kiểu REQUEST.
Ba điểm thực dụng khi dùng Lambda authorizer:
- Bật caching (
authorizerResultTtlInSeconds) — thiếu nó là mỗi request tốn thêm một lời gọi Lambda và một truy vấn DynamoDB. - Khoá cache là giá trị của identity source — với kiểu REQUEST dùng nhiều header, khai đủ chúng trong
identitySourceđể cache không trộn lẫn người dùng. - Trả về
contextđể truyền thông tin đã tra cứu (vai trò, gói dịch vụ) xuống backend — tránh việc backend phải truy vấn lại cùng dữ liệu.
A developer is creating an AWS Serverless Application Model (AWS SAM) template. It includes several AWS Lambda functions, an Amazon S3 bucket, and an Amazon CloudFront distribution. One Lambda function, running on Lambda@Edge, is integrated with the CloudFront distribution, while the S3 bucket serves as an origin for the distribution.
However, upon deploying the AWS SAM blueprint in the us-west-1 Region, the stack's creation fails.
What could be the possible reason for this failure?
-
A
Lambda@Edge functions can only be deployed in the us-east-1 Region.
-
B
Amazon S3 buckets serving as origins for CloudFront must be created in a separate Region from the CloudFront distribution.
-
C
AWS SAM templates are not supported in the us-west-1 Region.
-
D
AWS Lambda functions integrated with CloudFront cannot be deployed using AWS SAM templates.
Xem giải thích
Đáp án
A — Hàm Lambda@Edge chỉ triển khai được ở Region us-east-1.
Vì sao đúng
Đây là một hạn chế cứng và rất hay bị vấp: mọi hàm Lambda@Edge phải được tạo ở us-east-1 (N. Virginia).
Lý do nằm ở cách CloudFront hoạt động: nó là dịch vụ toàn cầu, và mặt phẳng điều khiển của nó đặt ở us-east-1. Khi bạn liên kết một hàm với distribution, CloudFront tự nhân bản mã hàm ra hơn 400 edge location trên toàn thế giới — nhưng bản gốc phải nằm ở us-east-1.
Đề nói triển khai stack ở us-west-1, nên hàm Lambda@Edge không tạo được ở đó và stack thất bại.
Cách sửa: tách template làm hai stack:
# Stack 1 — triển khai ở us-east-1
Resources:
HamEdge:
Type: AWS::Serverless::Function
Properties:
Handler: index.handler
Runtime: nodejs20.x
Role: !GetAtt VaiTroEdge.Arn # trust cả lambda + edgelambda
AutoPublishAlias: live # Lambda@Edge BẮT BUỘC dùng version cụ thể
# Stack 2 — triển khai ở us-west-1, tham chiếu ARN của hàm trên
Và execution role phải tin cậy cả hai service principal — thiếu một là liên kết thất bại:
{
"Effect": "Allow",
"Principal": {"Service": ["lambda.amazonaws.com", "edgelambda.amazonaws.com"]},
"Action": "sts:AssumeRole"
}
Vì sao các phương án khác sai
- B. Bucket S3 làm origin phải nằm ở Region KHÁC với distribution — vô lý: CloudFront không thuộc Region nào cả (nó là dịch vụ toàn cầu), và bucket origin đặt ở Region nào cũng được.
- C. SAM template không hỗ trợ ở
us-west-1— SAM hỗ trợ ở mọi Region. Nó chỉ là một macro của CloudFormation. - D. Lambda tích hợp với CloudFront không triển khai được bằng SAM — triển khai được, chỉ cần đúng Region và đúng cấu hình (có
AutoPublishAliashoặc trỏ tới version cụ thể).
Ghi nhớ
Các hạn chế của Lambda@Edge — chúng khác hẳn Lambda thường: | Hạn chế | Chi tiết | |---|---| | Region | BẮT BUỘC us-east-1 | | Version | phải trỏ tới version cụ thể, KHÔNG dùng $LATEST hay alias | | Biến môi trường | không hỗ trợ | | VPC | không gắn được | | Runtime | chỉ Node.js và Python | | Kích thước gói | 1 MB (viewer) / 50 MB (origin) | | Timeout | 5 giây (viewer) / 30 giây (origin) | | Bộ nhớ | 128 MB cố định (viewer) / tới 10 GB (origin) |
Hai dòng in đậm đầu tiên là nguyên nhân của hầu hết lỗi triển khai Lambda@Edge.
Bốn điểm gắn và giới hạn tương ứng: | Điểm | Chạy khi | Timeout | |---|---|---| | Viewer request | mọi request | 5 giây | | Origin request | cache miss | 30 giây | | Origin response | cache miss | 30 giây | | Viewer response | mọi response | 5 giây |
Và với các việc rất đơn giản (viết lại URL, thêm header, chuyển hướng), cân nhắc CloudFront Functions thay vì Lambda@Edge: nó chạy JavaScript thuần ở edge, nhanh hơn nhiều và rẻ hơn khoảng 6 lần — nhưng chỉ gắn được vào viewer request/response, không gọi được dịch vụ mạng, và giới hạn thời gian chạy dưới 1 mili giây.
Một lưu ý khi xoá: không xoá được distribution hay hàm Lambda@Edge ngay — CloudFront cần thời gian gỡ bản sao khỏi mọi edge location, thường vài tiếng.
A set of APIs are exposed to customers using Amazon API Gateway. These APIs have caching enabled on the API Gateway. Customers have asked for an option to invalidate this cache for each of the APIs.
What action can be taken to allow API customers to invalidate the API Cache?
-
A
Ask customers to add a query string parameter called
INVALIDATE_CACHE” when making an API call -
B
Ask customers to use AWS credentials to call the
InvalidateCacheAPI -
C
Ask customers to invoke an AWS API endpoint which invalidates the cache
-
D
Ask customers to pass an HTTP header called
Cache-Control:max-age=0
Xem giải thích
Đáp án
D — Yêu cầu khách hàng gửi HTTP header Cache-Control: max-age=0.
Vì sao đúng
API Gateway hỗ trợ client-side cache invalidation: client gửi header chuẩn HTTP, và API Gateway bỏ qua cache, gọi thẳng backend, rồi lưu lại kết quả mới.
curl -H "Cache-Control: max-age=0" \
https://abc123.execute-api.ap-southeast-1.amazonaws.com/prod/du-lieu
Điểm quan trọng: quyền này phải được cấp tường minh, nếu không bất kỳ ai cũng làm rỗng cache của bạn được:
{
"Effect": "Allow",
"Action": "execute-api:InvalidateCache",
"Resource": "arn:aws:execute-api:ap-southeast-1:123456789012:abc123/prod/GET/du-lieu"
}
Và trong stage settings có ba lựa chọn cho hành vi khi client chưa được cấp quyền mà vẫn gửi header: | Lựa chọn | Kết quả | |---|---| | Ignore | bỏ qua header, trả về từ cache (mặc định) | | Fail with 403 | từ chối request | | Ignore + thêm header cảnh báo | trả từ cache, kèm cảnh báo |
Đây đúng là thứ đề cần: một cơ chế khách hàng tự nhúng vào ứng dụng của họ, chỉ bằng một header HTTP chuẩn.
Vì sao các phương án khác sai
- C. Yêu cầu khách hàng gọi một AWS API endpoint để làm rỗng cache — có API
flushStageCache, nhưng nó làm rỗng TOÀN BỘ cache của cả stage và đòi quyền quản trị API Gateway. Không thể cấp quyền đó cho khách hàng bên ngoài. - B. Yêu cầu khách hàng dùng AWS credentials gọi API
InvalidateCache— không có API độc lập tênInvalidateCache.execute-api:InvalidateCachelà một quyền IAM, không phải một lời gọi API riêng — nó chỉ kiểm soát việc headerCache-Controlcó được chấp nhận hay không. - A. Yêu cầu khách hàng thêm query string
INVALIDATE_CACHE— không tồn tại. Ngược lại, query string là MỘT PHẦN của khoá cache: thêm tham số lạ sẽ tạo ra một mục cache MỚI, chứ không làm mất mục cũ. (Đó cũng là mẹo "lách" thô sơ mà người ta hay dùng — nhưng nó làm phình cache chứ không phải invalidate.)
Ghi nhớ
Cache của API Gateway: | Thuộc tính | Giá trị | |---|---| | Bật ở mức | stage (ghi đè được ở mức method) | | Kích thước | 0,5 GB đến 237 GB | | TTL | 0 – 3600 giây, mặc định 300 | | TTL = 0 | tắt cache | | Chi phí | tính theo GIỜ, không theo request | | Mã hoá | bật được cho dữ liệu cache |
Dòng chi phí đáng nhớ: cache tính tiền ngay cả khi không có request nào — nhớ tắt ở các stage dev và test, đây là khoản chi phí ẩn hay bị quên nhất của API Gateway.
Khoá cache mặc định là toàn bộ URL request, nhưng chọn được thành phần nào tham gia bằng cache key parameter (path param, query string, header). Điều này quan trọng khi response khác nhau theo Accept-Language hay theo phiên bản API — không khai đúng là khách hàng này nhận được dữ liệu cache của khách hàng kia.
Ba cách làm mới cache, theo phạm vi: | Cách | Phạm vi | |---|---| | Cache-Control: max-age=0 | một mục cụ thể, do client kích hoạt | | flushStageCache API | toàn bộ stage, cần quyền quản trị | | Đặt TTL ngắn | tự động, áp cho mọi mục |
A gaming application stores scores for players in an Amazon DynamoDB table that has four attributes: user_id, user_name, user_score, and user_rank. The users are allowed to update their names only. A user is authenticated by web identity federation.
Which set of conditions should be added in the policy attached to the role for the dynamodb:PutItem API call?
-
A
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_name}"
],
"dynamodb:Attributes": [
"user_name", "user_id"
]
}
}
-
B
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_name}"
],
"dynamodb:Attributes": [
"user_id"
]
}
}
-
C
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_id}"
],
"dynamodb:Attributes": [
"user_name", "user_id"
]
}
}
-
D
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": [
"${www.amazon.com:user_id}"
],
"dynamodb:Attributes": [
"user_name"
]
}
}
Xem giải thích
Đáp án
D — Điều kiện với dynamodb:LeadingKeys = ${www.amazon.com:user_id} và dynamodb:Attributes = ["user_name"].
Vì sao đúng
Có hai quyết định trong câu này, và cả hai đều xuất phát từ đề bài.
Quyết định 1 — LeadingKeys phải là user_id, không phải user_name.
dynamodb:LeadingKeys giới hạn người dùng chỉ thao tác được trên item có partition key khớp danh tính của họ. Mà partition key của bảng là user_id, nên biến thay thế phải là ${www.amazon.com:user_id}.
Dùng user_name sẽ so sánh sai trường — và vì user_name là thứ người dùng tự đổi được, dùng nó làm khoá phân quyền còn là lỗ hổng bảo mật.
Quyết định 2 — Attributes chỉ gồm user_name.
Đề nói rõ: "users are allowed to update their names only". dynamodb:Attributes liệt kê những thuộc tính người dùng được phép động vào, nên danh sách chỉ được có user_name.
{
"Effect": "Allow",
"Action": "dynamodb:PutItem",
"Resource": "arn:aws:dynamodb:*:*:table/GameScores",
"Condition": {
"ForAllValues:StringEquals": {
"dynamodb:LeadingKeys": ["${www.amazon.com:user_id}"],
"dynamodb:Attributes": ["user_name"]
}
}
}
Kết quả: người dùng chỉ sửa được tên của chính mình, không đụng được vào user_score hay user_rank — và không đụng được vào bản ghi của người khác.
Vì sao các phương án khác sai
- C.
LeadingKeys=user_idnhưngAttributes=["user_name", "user_id"]— đây là phương án gần nhất, và nó sai ở vế thứ hai: cho phép sửa cảuser_idnghĩa là người dùng đổi được khoá chính — tức là ghi đè lên bản ghi của người khác. Lỗ hổng nghiêm trọng. - A.
LeadingKeys=user_name,Attributes=["user_name", "user_id"]— sai cả hai vế. - B.
LeadingKeys=user_name,Attributes=["user_id"]— sai cả hai, và còn mâu thuẫn với đề: nó cho sửauser_idnhưng không cho sửauser_name— ngược hẳn yêu cầu.
Ghi nhớ
Các khoá điều kiện dành riêng cho DynamoDB — chúng cho phép phân quyền tới từng dòng và từng cột: | Khoá | Giới hạn | |---|---| | dynamodb:LeadingKeys | chỉ item có partition key khớp | | dynamodb:Attributes | chỉ những thuộc tính được liệt kê | | dynamodb:Select | ép dùng SPECIFIC_ATTRIBUTES | | dynamodb:ReturnValues | giới hạn dữ liệu trả về |
Ba toán tử tập hợp, và chọn đúng rất quan trọng: | Toán tử | Nghĩa | |---|---| | ForAllValues:StringEquals | MỌI giá trị trong request phải nằm trong danh sách cho phép | | ForAnyValue:StringEquals | ít nhất một giá trị khớp — quá lỏng cho mục đích này | | StringEquals | so sánh giá trị đơn |
Với dynamodb:Attributes, phải dùng ForAllValues — nếu dùng ForAnyValue, người dùng chỉ cần đưa user_name vào request là được phép sửa mọi thuộc tính khác kèm theo.
Các biến thay thế theo nhà cung cấp danh tính:
${www.amazon.com:user_id} Login with Amazon
${graph.facebook.com:id} Facebook
${accounts.google.com:sub} Google
${cognito-identity.amazonaws.com:sub} Cognito identity pool
${aws:userid} danh tính IAM
Và một lưu ý về PutItem cụ thể: nó thay thế toàn bộ item, nên với ràng buộc Attributes chỉ có user_name, request phải không chứa các thuộc tính khác. Trong thực tế, UpdateItem an toàn hơn cho kịch bản này vì nó chỉ sửa đúng trường được nêu.
A company has transferred some of its confidential documents to a private Amazon S3 bucket that is not publicly accessible. Now, the company intends to build a serverless application that allows its staff to securely share these files with others.
Which AWS service should the company utilize to ensure secure file sharing and access?
-
A
S3 Access Control Lists (ACLs)
-
B
S3 presigned URLs
-
C
Amazon Cognito identity pool
-
D
AWS Identity and Access Management (IAM) roles
Xem giải thích
Đáp án
B — S3 presigned URL.
Vì sao đúng
Yêu cầu: bucket vẫn riêng tư, nhưng nhân viên chia sẻ được tệp cho người khác một cách an toàn, trong một ứng dụng serverless.
Presigned URL làm đúng việc đó: một URL mang chữ ký và thời hạn, cho phép tải đúng một object mà không cần mở bucket ra công khai và không cần người nhận có tài khoản AWS:
url = s3.generate_presigned_url(
'get_object',
Params={'Bucket': 'tai-lieu-mat', 'Key': 'hop-dong-2026.pdf'},
ExpiresIn=900 # hết hạn sau 15 phút
)
Cách nó hoạt động: URL mang chữ ký tạo từ thông tin xác thực của ứng dụng, cộng với thời điểm hết hạn nằm ngay trong chữ ký. S3 xác minh chữ ký, kiểm hạn, rồi mới cho tải.
| Đặc điểm | Chi tiết |
|---|---|
| Bucket vẫn riêng tư | không mở public chút nào |
| Có thời hạn | tối đa 7 ngày với SigV4 |
| Quyền kế thừa | không vượt quá quyền của bên tạo URL |
| Dùng cho | GetObject và PutObject |
| Người nhận | không cần tài khoản AWS |
Kiến trúc serverless điển hình: API Gateway → Lambda sinh presigned URL → trả về cho nhân viên → nhân viên gửi link đi. Tệp không bao giờ đi qua Lambda, nên không vướng giới hạn payload và không tốn thời gian chạy.
Vì sao các phương án khác sai
- A. S3 Access Control Lists (ACLs) — cách cũ và có ba vấn đề: phải đặt ACL cho từng object, không có thời hạn, và quan trọng nhất — từ tháng 4/2023, AWS tắt ACL theo mặc định cho bucket mới (
Object Ownership: Bucket owner enforced), khiến ACL hoàn toàn không có tác dụng. - C. Cognito identity pool — cấp credential AWS cho người dùng, nhưng nó đòi người nhận đăng nhập qua một nhà cung cấp danh tính. Với việc chia sẻ tệp cho người bên ngoài, đó là rào cản không cần thiết.
- D. IAM role — cấp quyền cho danh tính AWS. Người nhận tệp bên ngoài không có danh tính AWS, và tạo role cho từng người là bất khả thi (giới hạn 1.000 role mỗi tài khoản).
Ghi nhớ
Các cơ chế kiểm soát truy cập S3, theo phạm vi: | Cơ chế | Phạm vi | Thời hạn | |---|---|---| | Presigned URL | một object, một người | có, tối đa 7 ngày | | Bucket policy | cả bucket hoặc prefix | tĩnh | | IAM policy | theo danh tính AWS | tĩnh | | CloudFront signed URL/cookie | qua CDN | có, kèm giới hạn IP | | ACL | từng object | đã lỗi thời |
So sánh hai loại signed URL: | | S3 presigned | CloudFront signed | |---|---|---| | Tạo bằng | credential IAM | cặp khoá riêng | | Thời hạn tối đa | 7 ngày | không giới hạn | | Giới hạn theo IP | ❌ | ✅ | | Qua CDN | ❌ | ✅ |
Ba lưu ý thực dụng:
- Thời hạn kế thừa từ credential tạo URL. URL tạo bằng credential tạm thời của Lambda role sẽ hết hiệu lực khi credential đó hết hạn — thường sớm hơn
ExpiresInbạn đặt. - Đặt thời hạn ngắn nhất có thể. URL bị chuyển tiếp cho người khác thì ai cầm cũng dùng được.
- Presigned URL cho
PutObjectrất hữu ích: cho phép client tải tệp thẳng lên S3, không đi qua ứng dụng — tránh giới hạn payload và giảm tải cho máy chủ.
A serverless application is used to process customer information and outputs a JSON file to an Amazon S3 bucket. AWS Lambda is used for processing the data. The data is sensitive and should be encrypted.
How can a Developer modify the Lambda function to ensure the data is encrypted before it is uploaded to the S3 bucket?
-
A
Use the S3 managed key and call the
GenerateDataKeyAPI to encrypt the file -
B
Enable server-side encryption on the S3 bucket and create a policy to enforce encryption
-
C
Use the default KMS key for S3 and encrypt the file using the Lambda code
-
D
Use the
GenerateDataKeyAPI, then use the data key to encrypt the file using the Lambda code
Xem giải thích
Đáp án
D — Dùng GenerateDataKey, rồi dùng data key đó để mã hoá tệp trong mã của Lambda.
Vì sao đúng
Đề yêu cầu dữ liệu được mã hoá TRƯỚC KHI tải lên S3 — tức là client-side encryption, do chính hàm Lambda thực hiện.
Và vì tệp JSON có thể vượt quá giới hạn 4 KB của kms:Encrypt, cách đúng là envelope encryption:
import boto3, base64, json
from cryptography.fernet import Fernet
kms = boto3.client('kms')
s3 = boto3.client('s3')
def lambda_handler(event, context):
du_lieu = json.dumps(xu_ly(event)).encode('utf-8')
# 1. Xin data key — KMS trả về CẢ HAI dạng
r = kms.generate_data_key(KeyId='alias/khoa-khach-hang', KeySpec='AES_256')
# 2. Mã hoá NGAY TRONG LAMBDA
f = Fernet(base64.urlsafe_b64encode(r['Plaintext']))
du_lieu_ma = f.encrypt(du_lieu)
# 3. Xoá khoá bản rõ khỏi bộ nhớ
del r['Plaintext']
# 4. Tải lên: dữ liệu đã mã hoá + khoá đã mã hoá lưu trong metadata
s3.put_object(
Bucket='du-lieu-khach-hang',
Key='ket-qua.json.enc',
Body=du_lieu_ma,
Metadata={'khoa-ma': base64.b64encode(r['CiphertextBlob']).decode()}
)
Điểm mấu chốt: dữ liệu rời khỏi Lambda ở dạng đã mã hoá, nên S3 không bao giờ thấy bản rõ. Đó là khác biệt với server-side encryption.
Vì sao các phương án khác sai
- B. Bật server-side encryption trên bucket và tạo policy bắt buộc — đây là phương án đáng bàn nhất, và nó rất tốt trong thực tế nhưng không đáp ứng đúng đề: với SSE, dữ liệu rời Lambda ở dạng BẢN RÕ (được bảo vệ bởi TLS trên đường truyền), rồi S3 mới mã hoá khi ghi xuống đĩa. Đề yêu cầu mã hoá trước khi tải lên, và đây cũng là mô tả nhiệm vụ "modify the Lambda function" — tức là việc phải làm trong mã.
- C. Dùng khoá KMS mặc định của S3 và mã hoá tệp bằng mã Lambda — mâu thuẫn nội tại:
aws/s3là AWS managed key dành riêng cho S3, bạn không gọi trực tiếp nó từ mã ứng dụng để mã hoá dữ liệu tuỳ ý. Muốn client-side thì phải dùng CMK của riêng bạn. - A. Dùng "S3 managed key" rồi gọi
GenerateDataKey— cũng mâu thuẫn: SSE-S3 dùng khoá do S3 quản lý hoàn toàn, bạn không thấy và không gọi được khoá đó.GenerateDataKeylà API của KMS, hoạt động với CMK — không phải với khoá của SSE-S3.
Ghi nhớ
Ba lớp mã hoá cho dữ liệu vào S3: | Lớp | Ai mã hoá | S3 thấy bản rõ? | |---|---|---| | In transit (TLS) | tự động | — | | Server-side (SSE) | S3 | ✅ CÓ | | Client-side | ứng dụng của bạn | ❌ KHÔNG |
Nhận dạng nhanh trong đề: | Đề nói | Chọn | |---|---| | "encrypted BEFORE it is uploaded", "client-side", "end-to-end" | GenerateDataKey + mã hoá trong mã | | "encrypted at rest", "S3 must encrypt" | SSE-S3 hoặc SSE-KMS |
| API của KMS | Dùng khi | Giới hạn |
|---|---|---|
Encrypt |
dữ liệu nhỏ | ≤ 4 KB |
GenerateDataKey |
dữ liệu lớn — envelope encryption | không giới hạn |
GenerateDataKeyWithoutPlaintext |
tạo sẵn khoá để dùng sau | — |
Decrypt |
giải mã data key | ≤ 4 KB |
Ba nguyên tắc khi làm client-side encryption:
- Xoá khoá bản rõ khỏi bộ nhớ ngay sau khi dùng.
- Lưu khoá đã mã hoá cùng dữ liệu (metadata của object là chỗ tiện) — mất nó là mất dữ liệu vĩnh viễn.
- Dùng encryption context để ràng buộc khoá với ngữ cảnh và có vết kiểm toán trong CloudTrail.
Và trong thực tế, nên dùng AWS Encryption SDK hoặc S3 Encryption Client thay vì tự viết — chúng đã cài đặt sẵn toàn bộ mẫu này, kèm định dạng thông điệp chuẩn và data key caching.
A Developer is troubleshooting an issue with a DynamoDB table. The table is used to store order information for a busy online store and uses the order date as the partition key. During busy periods writes to the table are being throttled despite the consumed throughput being well below the provisioned throughput.
According to AWS best practices, how can the Developer resolve the issue at the LOWEST cost?
-
A
Increase the read and write capacity units for the table
-
B
Add a global secondary index to the table
-
C
Use an Amazon SQS queue to buffer the incoming writes
-
D
Add a random number suffix to the partition key values
Xem giải thích
Đáp án
D — Thêm hậu tố ngẫu nhiên vào giá trị của partition key.
Vì sao đúng
Triệu chứng trong đề là chữ ký của hot partition: ghi bị throttle trong khi throughput tiêu thụ còn thấp hơn nhiều so với mức đã cấp.
Nguyên nhân nằm ở thiết kế khoá: partition key là ngày đặt hàng. Nghĩa là toàn bộ đơn hàng trong một ngày dồn vào đúng MỘT partition:
Cấp phát: 1.000 WCU, DynamoDB chia cho ~10 partition → mỗi partition ~100 WCU
partition "2026-08-05" → nhận 100% lượng ghi → chạm trần 100 WCU → THROTTLE
partition "2026-08-04" → 0 ghi (ngày cũ)
partition "2026-08-03" → 0 ghi
...
Tổng tiêu thụ trông rất thấp so với 1.000 WCU, nhưng một partition đã hết chỗ.
Write sharding giải quyết bằng cách rải một ngày ra nhiều partition:
import random
def ghi_don_hang(ngay, don_hang):
hau_to = random.randint(0, 9) # 10 shard
table.put_item(Item={
'ngay_shard': f'{ngay}-{hau_to}', # "2026-08-05-7"
'don_hang_id': don_hang['id'],
**don_hang
})
Giờ một ngày trải trên 10 partition, và năng lực ghi cho ngày đó tăng gấp 10.
Khi đọc, truy vấn cả 10 shard rồi gộp lại:
ket_qua = []
for i in range(10):
r = table.query(KeyConditionExpression=Key('ngay_shard').eq(f'{ngay}-{i}'))
ket_qua.extend(r['Items'])
Và đây là cách chi phí thấp nhất: nó không tốn thêm đồng nào — chỉ là đổi cách sinh giá trị khoá.
Vì sao các phương án khác sai
- A. Tăng RCU và WCU cho bảng — tốn tiền mà không giải quyết được gốc: DynamoDB chia năng lực đều cho các partition, nên tăng tổng WCU chỉ nâng trần của partition nóng lên một chút, trong khi bạn trả tiền cho toàn bộ phần dư ở các partition khác. Với hot partition thật sự, không lượng WCU nào là đủ.
- C. Dùng SQS làm đệm cho các lần ghi — san phẳng đỉnh được, nhưng nó chỉ trì hoãn vấn đề: nếu tốc độ ghi trung bình vẫn vượt năng lực của partition nóng, hàng đợi sẽ dài ra vô hạn. Ngoài ra nó thêm dịch vụ, thêm độ trễ, và biến việc ghi thành bất đồng bộ.
- B. Thêm GSI vào bảng — không liên quan tới throttle ghi ở bảng gốc, và thực tế còn làm tệ hơn: mỗi lần ghi vào bảng gốc kéo theo một lần ghi vào GSI, tốn thêm WCU.
Ghi nhớ
Cách nhận biết hot partition: | Dấu hiệu | Kết luận | |---|---| | ThrottledRequests > 0 nhưng ConsumedWriteCapacityUnits thấp | hot partition | | Tiêu thụ chạm sát mức cấp phát | thiếu capacity thật |
Bảng chẩn đoán này rất hữu ích: hai nguyên nhân trông giống nhau (đều là throttle) nhưng cách chữa hoàn toàn khác.
Nguyên tắc chọn partition key: | Nên | Không nên | |---|---| | Nhiều giá trị khác nhau (user_id, don_hang_id) | ít giá trị (trạng thái, loại) | | Phân bố đều | theo thời gian (ngày, giờ) ← lỗi của đề bài | | Truy cập rải đều | có giá trị "nóng" (một khách hàng lớn) |
Hai kiểu sharding: | Kiểu | Cách sinh hậu tố | Đặc điểm | |---|---|---| | Ngẫu nhiên | random.randint(0, N) | rải đều nhất, phải query hết N shard | | Tính toán | hash(don_hang_id) % N | tra cứu một item chính xác được |
Kiểu thứ hai đáng cân nhắc nếu bạn cần đọc lại đúng một đơn hàng theo mã: từ mã đơn hàng bạn tính lại được shard, không phải quét cả 10.
(Ghi chú: DynamoDB có adaptive capacity tự dồn năng lực về partition nóng, và nó xử lý được phần lớn trường hợp lệch nhẹ. Nhưng với thiết kế khoá theo ngày như đề bài — nơi 100% lượng ghi vào một partition — nó không đủ.)