Sử dụng Nginx để truy cập tới một Private S3 Bucket

by khanhcd92
25 views

Bài toán

Mình được giao nhiệm vụ phát triển một ứng dụng quản lý chi tiêu cho khách hàng. Thông tin các hoá đơn và ảnh trong ứng dụng sẽ được lưu trên S3. Khách hàng có yêu cầu có thể xem được ảnh lưu trên S3 bằng domain của họ thay vì bằng đường link trực tiếp từ S3. Hệ thống Backend của họ đang sử dụng Nginx với Python Flask và mong muốn không sử dụng đến dịch vụ CloudFront.

Giải pháp

Sau hồi nguyên cứu mình đã tìm ra giải pháp là có thể dùng Nginx để truy cập tới một private S3 bucket.

Để có thể demo được giải pháp nên mình sẽ lược bỏ hệ thống cho nó đơn giản hơn so với hệ thống của khách hàng. Đầu tiên giả sử hệ thống trên AWS đã được cấu hình như bên dưới:

  • VPC(10.0.0.0/16) với public subnet và private subnet
  • VPC Endpoint cho s3
  • A static web on ECS Fargate with Nginx
  • 1 trang web tĩnh được triển khai trên dịch vụ ECS Fargate với việc dùng Nginx
  • 1 private S3 bucket để lưu ảnh của trang web.

Alt Text

Kết quả sau khi cấu hình xong chúng ta sẽ có 1 trang web như bên dưới. Nhưng hình ảnh mọi nguời thấy là hình ảnh được tải từ trên mạng. Alt Text

Bây giờ mình sẽ cần thay thể ảnh trên mạng này với ảnh trên S3. Để làm được điều đó các bạn theo dõi tiếp bên dưới nhé. Alt Text

Thiết lập Nginx và S3

1. Thay đổi S3 bucket policy để chỉ cho phép lấy dữ liệu từ VPC Endpoint.

{
    "Version": "2008-10-17",
    "Id": "PolicyForCloudFrontPrivateContent",
    "Statement": [
        {
            "Sid": "Access-to-specific-VPCE-only",
            "Effect": "Allow",
            "Principal": "*",
            "Action": "s3:GetObject",
            "Resource": "arn:aws:s3:::demo-static-s3/*",
            "Condition": {
                "StringEquals": {
                    "aws:sourceVpce": "vpce-0d92e50f230bc8070"
                }
            }
        }
    ]
}

2. Tiếp theo là việc quan trọng nhất, chúng ta sẽ cần cấu hình Nginx để có thể tải ảnh từ private S3

location ~^/image/(.+)$ {
        resolver 10.0.0.2;
        proxy_pass http://s3-ap-southeast-1.amazonaws.com/demo-static-s3/image/$1; 
}
  • resolver: Địa chỉ IP của DNS server trong VPC mà mình đã tạo.

    Ví dụ, VPC của mình tạo có CIRD là 10.0.0.0/16. AWS sẽ dùng 5 IPs bên dưới cho các mục đích bên của họ và mình sẽ không thể sử dụng các IP đó.

    • 10.0.0.0: Network address.
    • 10.0.0.1: Reserved by AWS for the VPC router.
    • 10.0.0.2: Reserved by AWS. The IP address of the DNS server is the base of the VPC network range plus two. For VPCs with multiple CIDR blocks, the IP address of the DNS server is located in the primary CIDR. We also reserve the base of each subnet range plus two for all CIDR blocks in the VPC. For more information, see Amazon DNS server.
    • 10.0.0.3: Reserved by AWS for future use.
    • 10.0.0.255: Network broadcast address. We do not support broadcast in a VPC, therefore we reserve this address.

    => Resolver sẽ có giá trị là 10.0.0.2

    Tham khảo: https://docs.aws.amazon.com/vpc/latest/userguide/VPC_Subnets.html

  • proxy_pass: s3 link

    Định dạng: http://s3-ap-southeast-1.amazonaws.com/[main_bucket]/[sub_bucket]/$1

3. Thay đổi dường dẫn của tải ảnh của trang web

<div class="container">
    <h1>Hey there</h1>
    <img src="https://cleandevs.com/image/668c1d479e27bb8750823655c83a6c9bd90263f9_hq.jpg"/>
  </div>

4. Cuối cùng mình sẽ deploy lại trang web lên dịch vụ ECS Fargate. Kết quả sẽ như hình bên dưới. Trang web đã hiển thị ảnh được tải từ private S3 bucket

Alt Text

Leave a Comment

* By using this form you agree with the storage and handling of your data by this website.

You may also like