11/08/2018, 20:44

Sử dụng ENV variables thay vì hardcode các thông tin bảo mật cho WordPress

Thấm thoát cũng đã được 10 năm kể từ khi tôi đụng vào WordPress. Hôm qua tôi được một người bạn nhờ thay đổi một số CSS cho trang WordPress của họ. Tôi khá là ngạc nhiên sau từng đấy năm WordPress vẫn khuyến khích người dùng hardcode các thông tin bảo mật của DB vào trong file wp-config.php. Điều ...

Thấm thoát cũng đã được 10 năm kể từ khi tôi đụng vào WordPress. Hôm qua tôi được một người bạn nhờ thay đổi một số CSS cho trang WordPress của họ. Tôi khá là ngạc nhiên sau từng đấy năm WordPress vẫn khuyến khích người dùng hardcode các thông tin bảo mật của DB vào trong file wp-config.php. Điều này khá là tai hại bởi vì nếu người dùng sử dụng git chẳng hạn, toàn bộ thông tin nhạy cảm này sẽ được lưu lại, có thể bạn sẽ tranh luận là không nên commit file wp-config.php vào repo (tôi cũng không rõ là đến thời điểm này thì git có phổ biến trong giới WP không nữa vì cái site của bạn tôi vẫn host thông qua CPanel và FTP...). Dù gì đi nữa thì theo tôi, người dùng nên tuân theo luật Config của 12 factor app. Nói nôm na lại là thay vì hardcode thì sử dụng UNIX env variables.

UNIX environments là gì?

Cho độc giả nào không biết nhiều về UNIX, UNIX có cung cấp nhiều chức năng lợi hại giúp ích cho việc tương tác shell rất dễ dàng. UNIX cho phép người dùng tạo ra các biến lưu giữ thông tin, người dùng có thể gán biến thông qua lệnh export:

export BAN_CO_YEU_PHP='khong'

và có thể truy xuất biến thông qua $_ENV['BAN_CO_YEU_PHP'] hay getenv('BAN_CO_YEU_PHP') trong PHP.

Áp dụng UNIX env cho WP config

Trong file wp-config.php bạn có thể tìm các dòng sau:

define('DB_NAME', 'database_name_here');
define('DB_USER', 'username_here');
define('DB_PASSWORD', 'password_here');
define('DB_HOST', 'localhost');

đây là những biến giá trị mà PHP sử dụng để kết nối vào DB. Chúng ta thay đổi chúng thành:

define('DB_NAME', getenv('DB_NAME'));
define('DB_USER', getenv('DB_USER'));
define('DB_PASSWORD', getenv('DB_PASSWORD'));
define('DB_HOST', getenv('DB_HOST'));

và xin lưu ý một điều là đừng quên gán những biến ở trên trong môi trường shell của bạn:

export DB_NAME='db_name'
export DB_USER='db_user'
export DB_PASSWORD='db_password'
export DB_HOST='localhost'

Xong! Bạn có thể chạy server và kiểm tra kết quả.

Sử dụng phpdotenv để lưu lại UNIX env trên môi trường development

Xin lưu ý trên một số môi trường thì các thay đổi trên có thể bị mất khi bạn đóng shell hiện hành lại. Ở hầu hết môi trường production server thì các biến trên được lưu lại trên hệ thống và không bị mất sau nhiều lần deploy, nhưng ở môi trường development trên máy riêng của bạn thì khá là khó chịu nếu phải cứ đánh lại các lệnh export ở trên sau mỗi lần đóng shell. Tiếp theo tôi sẽ chỉ bạn một kỹ thuật khác để khắc phục.

Việc đầu tiên cần làm là chúng ta phải cài đặt gói phpdotenv:

curl -s http://getcomposer.org/installer | php
php composer.phar require vlucas/phpdotenv
php composer.phar install

Lệnh ở trên sẽ cài đặt trình quản lý gói composer (giống Bundler nếu bạn là dân lập trình Ruby), sau đó chúng ta nói composer tìm và cái cho chúng ta phpdotenv. Bạn có thể tìm thấy file composer.json và composer.lock nếu cài đặt hoàn thành. Xin lưu ý là toàn bộ gói đều được cho vào thư mục vendor.

Tiếp theo chúng ta yêu cầu WordPress load phpdotenv, tôi thay đổi file wp-config.php và đưa vào trên đầu:

<?php

require __DIR__ . '/vendor/autoload.php';
Dotenv::load(__DIR__);
Dotenv::required(array('DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASSWORD'));

Dòng require __DIR__ . '/vendor/autoload.php'; là để tìm toàn bộ file gói chúng ta cài đặt thông qua composer (trong đó có kèm gói phpdotenv). Và Dotenv::load(__DIR__); là để chạy Dotenv và kêu Dotenv tìm file .env trong thư mục hiện hành. Và Dotenv::required(array('DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASSWORD')); đề nghị người dùng cài các biến trong file .env nếu không sẽ trả về lỗi.

Việc cuối cùng bây giờ là tạo 1 file .env với nội dung:

DB_NAME='db_name'
DB_USER='db_user'
DB_PASSWORD='db_password'
DB_HOST='localhost'

Chạy server để kiểm tra, nếu không có gì sai sót, server sẽ chạy bình thường.

Sau thay đổi trên thì chúng ta đảm bảo các biến UNIX không bị mất đi nếu đóng shell.

Có một nhược điểm của phương pháp trên, thứ nhất là bạn không cần code trên trong môi trường production, tiếc là mình không có biết cách nào để phân biệt môi trường production hay môi trường development, dường như WordPress không có cách kiểm tra. Và vâng, mình nghĩ về cách kiểm tra xem có phải localhost không nhưng tiếc là phương pháp này không áp dụng đc. Thế nên nếu bạn nào khó tính hơn 1 tí thì xin tham khảo công cụ khác, mình xin gợi ý công cụ direnv, công cụ này được cài đặt riêng biệt và không giới thiệu thêm bất ký dependency nào cho app của bạn cả.

Kết luận

Có rất nhiều thay đổi về cách cấu hình app để đảm bảo tính bảo mật ở các cộng đồng như Ruby hay Python, tiếc là bên cộng đồng WordPress thì không mấy là tập trung về mảng này, hầu hết cách thức deploy vẫn rất cũ, dựa trên FTP, CPanel thay vì Git + Heroku. Tôi hi vọng nếu có thời gian rảnh sẽ viết hẳn một bài cách deploy hoàn chỉnh WP đạt đủ yêu cầu của 12 factor app.

0