Bảo mật và tăng tốc Drupal CMS với Amazon CloudFront, AWS WAF và Edge Functions

CloudFront là dịch vụ mạng phân phối nội dung (CDN) cung cấp sự cải thiện về bảo mật và tốc độ cho nội dung được cung cấp thông qua nó. Điều này đúng cho cả nội dung tĩnh có thể lưu trữ và nội dung động nhờ vào việc tối ưu hóa được thực hiện ở các giai đoạn khác nhau của chu kỳ yêu cầu/phản hồi. Bên cạnh đó, AWS WAF là dịch vụ tường lửa ứng dụng web được quản lý hoàn toàn tích hợp với CloudFront, Application Load Balancer (ALB), Amazon API Gateway, và AWS AppSync. Hơn nữa, nó cung cấp các cơ chế để bảo vệ ứng dụng của bạn khỏi các cuộc tấn công ở Layer 7 (lớp ứng dụng của mô hình OSI).

Hệ thống quản lý nội dung (CMS) giúp chủ sở hữu nội dung tạo và duy trì các bài viết và phần trên trang web mà không cần kiến thức chuyên sâu về cách hiển thị nó trên trình duyệt. Là một phần của CMS, có một phần quản trị nơi thực hiện cập nhật nội dung và một trang web công khai để người xem tiêu thụ nội dung.

Khi sử dụng Drupal, một hệ thống quản lý nội dung phổ biến, bạn có thể thiết lập các tên miền riêng biệt để truy cập phần thực hiện cập nhật nội dung (chúng ta sẽ gọi là “tên miền admin”) và cho trang web công khai. Hoặc, bạn có thể sử dụng cùng tên miền cho cả hai. Trong bài viết này, bạn sẽ tìm hiểu một số chiến lược để cải thiện bảo mật trong việc cung cấp nội dung bằng cách sử dụng CloudFront và AWS WAF trong hai kịch bản này.

Kịch bản 1: Tên miền riêng biệt cho người quản trị và người xem nội dung Trong cài đặt này, tên miền admin và trang web công khai có tên miền khác nhau. Ở đây, bạn muốn hạn chế người xem ẩn danh khỏi việc truy cập các mẫu URL liên quan đến các hoạt động cập nhật nội dung, ví dụ: /node, /admin, /core, /batch, v.v.

Để thực hiện điều này, hãy tạo hai cấu hình CloudFront và WAF độc lập với các quy tắc tường lửa tương ứng để bảo vệ hệ thống Drupal phía sau.

Đối với người xem, bạn sẽ định nghĩa các luật tùy chỉnh trong AWS WAF để chặn tất cả các mẫu đường dẫn liên quan đến các phần quản trị của CMS. CloudFront sẽ được cấu hình để lưu trữ và phục vụ nội dung một cách an toàn qua HTTPS tại vị trí edge gần nhất, dẫn đến tải trang nhanh hơn. Khi lưu lượng tăng lên, CloudFront phục vụ nhiều yêu cầu hơn từ nội dung đã được lưu trữ tại các vị trí edge. Điều này giảm yêu cầu gốc và tối ưu hóa cơ sở hạ tầng backend của bạn.

Đối với người dùng quản trị, bạn sẽ định nghĩa các luật tùy chỉnh trong AWS WAF thứ hai của bạn chỉ cho phép yêu cầu dựa trên một cookie phiên đặc biệt được thiết lập bởi Drupal cho người dùng được ủy quyền. Trong phân phát CloudFront thứ hai được sử dụng cho quyền truy cập quản trị, lưu trữ tắt và CloudFront hoạt động để tăng tốc các cuộc gọi API cập nhật nội dung động bằng các kỹ thuật như sử dụng lại các kết nối cố định qua các yêu cầu, cửa sổ tắc nghẽn TCP được tối ưu hóa và khôi phục phiên TLS.

Trong cả hai trường hợp, CloudFront áp dụng tối ưu hóa cuối cùng, bao gồm nén nội dung và thời gian truyền Round-trip Bandwidth và Bottleneck (BBR) trên TCP để giảm thời gian tải trang thấp hơn cho người xem.

Nếu nguồn gốc của bạn được triển khai trong AWS, thì lưu lượng từ vị trí edge đến nguồn gốc AWS của bạn nằm trong mạng AWS, dẫn đến trải nghiệm phân phối nội dung đáng tin cậy hơn cho người dùng cuối của bạn.

Đây là cài đặt được đề xuất, vì nó cho phép duy trì kiểm soát truy cập và kiểm soát bộ nhớ cache chi tiết qua các tập hợp người dùng khác nhau.

Kịch bản 2: Cùng tên miền cho người dùng quản trị và người xem nội dung Trong cách tiếp cận này, bạn có cùng tên miền cho việc quản lý cập nhật nội dung và phục vụ người xem. Để bảo mật và tăng tốc backend Drupal của bạn, bạn sẽ thiết lập một cấu hình CloudFront và AWS WAF duy nhất.

Để cho phép người dùng quản trị có khả năng quản lý cập nhật nội dung, bạn sẽ định nghĩa các quy tắc AWS WAF tùy chỉnh để kiểm tra xem người dùng được ủy quyền (được chỉ định bằng một cookie phiên đặc biệt được thiết lập bởi Drupal) có kết nối đến các mẫu đường dẫn URL bị hạn chế như /node, /admin, v.v. Do đó, các người xem ẩn danh cố gắng truy cập các liên kết này sẽ bị chặn. Quy tắc AWS WAF phải được áp dụng cho tất cả các mẫu URL quản trị ngoại trừ /user/login, được sử dụng cho mục đích đăng nhập và được phép cho tất cả người dùng.

Trong phân phối CloudFront, đối với tất cả các mẫu đường dẫn URL quản trị, tạo các định nghĩa Cache Behaviors riêng biệt được cấu hình để proxy các yêu cầu API cập nhật nội dung cùng với hỗ trợ cho phương thức HTTP POST. Hành vi bộ nhớ cache mặc định được đặt để lưu trữ và phục vụ các trang nội dung trang web (trang bài viết và mục) bằng phương thức HTTP GET.

Khi người dùng quản trị chỉnh sửa nội dung, hãy đảm bảo rằng các cập nhật gần đây nhất có thể thấy ngay lập tức mà không cần phải vô hiệu hóa bộ nhớ cache hoặc chờ đợi thời gian sống của trang (TTL) hết hạn. Để làm điều này, chúng tôi sử dụng một CloudFront Function đơn giản để bỏ qua bộ nhớ cache cho người dùng quản trị đã đăng nhập.

Sử dụng một chức năng CloudFront để bỏ qua bộ nhớ cache Việc xác định một tập hợp đã định sẵn các mẫu đường dẫn URL quản trị và bỏ qua bộ nhớ cache cho chúng khá dễ dàng. Tuy nhiên, các URL nội dung (trang bài viết và mục) được tạo động, và người dùng quản trị phải xem xét các cập nhật cho chúng ngay lập tức.

Để làm điều này, một CloudFront Function kiểm tra xem có tồn tại cookie phiên đặc biệt do Drupal thiết lập cho người dùng đã đăng nhập không. Nếu có, nó sẽ đặt một giá trị chuỗi ngẫu nhiên cho tham số truy vấn được cho phép. Tham số truy vấn này là duy nhất, được tạo ra trong quá trình triển khai và được bao gồm trong các định nghĩa CloudFront function và cache policy. Điều này giúp chúng tôi bỏ qua bộ nhớ cache cho tất cả các trang dành cho người dùng đã xác thực. Đồng thời, nó cho phép chúng tôi phục vụ nội dung từ bộ nhớ cache cho người xem ẩn danh, đối với họ, tham số truy vấn này không được đặt. Chức năng được kích hoạt cho tất cả ‘Yêu cầu Người xem’.

Mã chức năng CloudFront

var cookieName = “SESS”; var randomString = “SESS-randomstr”;

function handler(event) { var request = event.request; if(loggedInUser(request)){ request.querystring[randomString] = {value: “ran-“+Math.random()}; } else{ console.log(“not logged in user”) } return request; }

function loggedInUser(request) { return Object.keys(request.cookies).some(key => key.startsWith(cookieName)); }

Chức năng này định nghĩa hai biến để lưu trữ tên cookie phiên của Drupal (được truyền trong quá trình triển khai) và tham số truy vấn được tạo ra (điều này dựa trên tên cookie và AWS Stack ID). Tham số truy vấn này cũng được cho phép trong chính sách bộ nhớ cache, vì vậy nó là một phần của định nghĩa khóa bộ nhớ cache trong CloudFront.

Chức năng kiểm tra xem yêu cầu có đến từ người dùng đã đăng nhập bằng cách tìm kiếm tên cookie. Nếu có, nó đặt giá trị ngẫu nhiên cho tham số truy vấn được cho phép. Điều này đảm bảo rằng tất cả các yêu cầu được proxy trở lại nguồn gốc cho người dùng quản trị, người có thể xem xét cập nhật nội dung ngay lập tức. Đối với người xem ẩn danh, một phiên bản được lưu trữ trong bộ nhớ cache.

Trong kịch bản này, có sự phức tạp và chi phí bổ sung khi phục vụ lưu lượng.

Bây giờ, sau khi chúng ta đã bao quát hai cấu hình có thể có, trong phần còn lại của bài viết này, chúng ta sẽ đi qua quy trình thiết lập của một giải pháp tham khảo để thử nghiệm nó.

Triển khai Trước khi bắt đầu, bạn sẽ cần một hệ thống backend được cấp quyền bởi Drupal lắng nghe trên một đầu nối có sẵn công khai. Nếu bạn chưa có một hệ thống như vậy, bạn có thể sử dụng hướng dẫn bắt đầu sau đây để cài đặt nó.

Sau khi bạn đã có hệ thống backend Drupal, hãy sao chép kho lưu trữ GitHub tại đây và triển khai mẫu AWS CloudFormation có sẵn trong ‘templates/drupal-cf.yml’. Lưu ý rằng quá trình triển khai cần phải ở khu vực AWS ‘us-east-1’.

Tham số đầu vào mẫu CloudFormation Mẫu CloudFormation định nghĩa các tài nguyên AWS và cung cấp các tham số để cấu hình hệ thống của bạn phù hợp với một trong hai tình huống đã thảo luận trước đây. Khi bạn bắt đầu quá trình triển khai, nhập tên ‘Stack Name’, sau đó bạn sẽ nhận được một tập hợp các tham số cấu hình. Hãy hiểu rõ ý nghĩa của chúng.

Cấu Hình Backend Drupal

  • Điểm cuối Backend Drupal – Đây là tên miền công khai trỏ đến cài đặt Drupal hiện tại của bạn. Lưu ý rằng tên miền này phải khác với tên miền phục vụ cho người xem của bạn.
  • Backend lắng nghe trên giao thức https hoặc http? – Chọn ‘https’ nếu máy gốc của bạn lắng nghe các kết nối TLS.
  • Tên Cookie Drupal – Chúng tôi sẽ để giá trị mặc định là ‘SESS’ và cập nhật nó sau khi triển khai. Tham khảo phần ‘Lưu ý về Cookie Phiên Phi Drupal’ để biết thêm chi tiết.

Cấu Hình Frontend Drupal

  • Tên Miền (tùy chọn) – xác định tên miền được sử dụng bởi người xem để kết nối đến trang web của bạn. Tên miền này sẽ được ánh xạ vào phân phối CloudFront để phục vụ lưu lượng người xem. Nếu bỏ trống, bạn vẫn có thể phục vụ lưu lượng với tên miền mặc định của CloudFront được tạo ra và định dạng sẽ là ‘dxxxxx.cloudfront.net’.
  • Cấu Hình Quản trị – chọn ‘có’ nếu bạn muốn tạo cấu hình riêng biệt (tình huống 1) để phục vụ người xem và người quản trị. Nếu bạn chọn ‘không’, thì sẽ được tạo một phân phối CloudFront duy nhất và cấu hình AWS WAF (tình huống 2).
  • Tên Miền Quản trị (tùy chọn) – xác định tên miền thứ hai được sử dụng bởi người quản trị để quản lý cập nhật nội dung trên hệ thống quản lý nội dung Drupal. Tên miền này sẽ được ánh xạ vào phân phối CloudFront thứ hai nếu nó được tạo ra (tùy thuộc vào giá trị của tham số AdminConfig). Nếu bỏ trống, bạn vẫn có thể phục vụ với tên miền mặc định của CloudFront.

Lưu ý rằng khi một hoặc cả hai trường ‘Tên Miền’ và ‘Tên Miền Quản trị’ được chỉ định là tên miền thay thế cho phân phối CloudFront của bạn, bạn phải đính kèm một chứng chỉ TLS đáng tin cậy để xác minh quyền sử dụng tên miền. Triển khai này sẽ tạo các chứng chỉ cần thiết bằng AWS Certificate Manager cho các tên miền này và sử dụng xác minh dựa trên DNS để xác nhận quyền sở hữu của tên miền.

Cấu Hình DNS Amazon Route 53

  • HostedZoneId – được sử dụng để tạo bản ghi ‘Tên Miền’ và ‘Tên Miền Quản trị’ trong khu vực đặt chỗ Amazon Route 53 của bạn. Trường này là bắt buộc nếu cả hai tên miền đều được chỉ định.

Sau khi bạn chỉ định các tham số này, triển khai mẫu CloudFormation. Sau khi triển khai hoàn tất, các tài nguyên AWS được tạo ra phụ thuộc vào các tham số đầu vào được chỉ định trong quá trình triển khai.

Nếu ‘Bật cấu hình quản trị’ được đặt thành ‘có’ (phục vụ cho tình huống 1), bạn sẽ có hai phân phối CloudFront và mỗi phân phối này sẽ được liên kết với cấu hình AWS WAF riêng của nó. Trường ‘mô tả’ tương ứng của phân phối chỉ định xem nó đã được cấu hình cho người xem hay người quản trị.

Phân phối CloudFront với mô tả ‘Phân phối StackName cho việc phục vụ nội dung Drupal’ được sử dụng để phục vụ lưu lượng cho người xem cuối cùng của bạn. Phân phối này có một hành vi mặc định duy nhất trỏ đến ‘Điểm cuối Backend Drupal’ của bạn như được hiển thị ở dưới đây.

Hình 4: Hành vi bộ nhớ đệm CloudFront

Hành vi bộ nhớ đệm này được thiết kế để tối ưu hóa việc lưu trữ nội dung (sử dụng chính sách bộ nhớ đệm ‘Managed-CachingOptimized’). Tùy thuộc vào các tiêu đề ‘Cache-Control’ được gửi từ nguồn gốc, nội dung được lưu trữ với thời gian tồn tại (TTL) tối thiểu là 1 giây, TTL tối đa là 31536000 giây (365 ngày), và TTL mặc định là 86400 giây (1 ngày) khi không có tiêu đề cache-control cụ thể nào được chỉ định. Để biết thêm thông tin về cách CloudFront tôn trọng tiêu đề cache-control, hãy tham khảo tài liệu này.

Cấu hình AWS WAF liên quan với tên ‘StackName-ViewerWAFWebACL’ chặn tất cả các URL truy cập ‘admin’ bằng cách sử dụng quy tắc khớp regex. Một bộ quy tắc biểu thức chính quy với tên ‘StackName-DrupalAdminRegex’ được tạo và xác định các mẫu đường dẫn cho các URL ‘admin’ như sau. Cập nhật nhóm quy tắc regex này để bao gồm các mẫu URL bổ sung cần bị giới hạn.

^(/user/|/admin/) ^(/node/|/batch|/core/)

Một bản phân phối CloudFront thứ hai với mô tả ‘StackName-Phân phối Admin cho việc cập nhật nội dung Drupal’ được sử dụng bởi người dùng quản trị để quản lý việc cập nhật nội dung. Bản phân phối này có một hành vi mặc định duy nhất với nguồn gốc tương ứng với ‘Điểm cuối Backend Drupal’ và được đặt để không lưu trữ nội dung (sử dụng chính sách bộ nhớ đệm ‘Managed-CacheDisabled’).

Cấu hình này chuyển tất cả tiêu đề của người xem, chuỗi truy vấn và cookie (sử dụng chính sách yêu cầu nguồn ‘Managed-AllViewer’) để cập nhật nội dung ngay lập tức cho người dùng quản trị.

Tên cấu hình AWS WAF liên quan ‘StackName-AdminWAFWebACL’ chặn tất cả quyền truy cập không xác định (khi cookie phiên Drupal không được đặt) đối với các URL quản trị ngoại trừ trang đăng nhập.

Ngoài ra, nếu bạn đã chỉ định tên miền bằng cách sử dụng trường ‘Tên miền’ và ‘Tên miền Quản trị’, thì chúng sẽ được liên kết với các phân phối CloudFront tương ứng cùng với chứng chỉ ACM. Các tập hợp bản ghi Route 53 cũng được đặt, cho phép bạn phục vụ lưu lượng qua HTTPS bằng cách sử dụng tên miền thay thế.

Nếu ‘Bật cấu hình Quản trị’ được đặt thành ‘không’ (phù hợp với tình huống 2), sau đó mẫu CloudFormation triển khai một phân phối CloudFront duy nhất và cấu hình AWS WAF. Trong cấu hình này, phân phối CloudFront có hành vi lưu trữ tường minh để xác định mẫu URL quản trị có bộ nhớ đệm đã bị tắt, và hành vi bộ nhớ đệm mặc định phục vụ tất cả trang bài viết. Hành vi mặc định cũng được liên kết với chức năng CloudFront ‘Yêu cầu của Người xem’ mà, ngẫu nhiên một tham số truy vấn cho người dùng đã đăng nhập để đảm bảo rằng các cập nhật cho nội dung được thấy ngay lập tức, như đã giải thích trước đó trong phần ‘Sử dụng chức năng CloudFront để bỏ qua bộ nhớ đệm’.

Lưu ý về Cookie Phiên Drupal Trong triển khai ban đầu, chúng tôi để giá trị tham số đầu vào ‘Tên Cookie Drupal’ mặc định của nó là ‘SESS’, đây là tiền tố mặc định mà Drupal sử dụng cho các cookie phiên. Chúng tôi để nó không thay đổi trong quá trình triển khai vì Drupal đặt một tên cookie duy nhất cho mỗi tên miền máy chủ mà nó phục vụ, và tên thực tế sẽ có sẵn khi chúng tôi bắt đầu phục vụ thông qua CloudFront bằng cách sử dụng tên miền tùy chỉnh.

Do đó, khi triển khai hoàn tất, chúng tôi truy cập các phần quản trị của CMS và sử dụng công cụ phát triển của trình duyệt để xác định tên cookie thực tế bắt đầu bằng ‘SESS’. Chúng tôi sẽ sử dụng giá trị này để triển khai lại và cập nhật cùng một ngăn xếp CloudFormation, lần này chỉ cần cập nhật trường ‘Tên Cookie Drupal’ với giá trị mới. Điều này sẽ cập nhật cấu hình AWS WAF, chính sách bộ nhớ đệm và mã chức năng CloudFront để sử dụng các giá trị mới.

Kết luận Tóm lại, bạn đã tìm hiểu một số cấu hình để bảo mật và tăng tốc các nền tảng CMS dựa trên Drupal bằng cách sử dụng CloudFront, AWS WAF và các chức năng CloudFront. Tùy thuộc vào tình huống triển khai của bạn, chúng tôi hy vọng rằng bài viết này có ích.

Leave a comment