Rotate certificate in NGINX Open Source without restart
terngr
Posted on September 29, 2023
ตอนนี้ทีมทยอยย้ายเข้า Office ใหม่ตึก OASIS ในรูปเป็นห้องร้อง Karaoke เอ๊ยห้องประชุมขนาดย่อม ไว้ร้อง Karaoke ได้เต็มที่ 8 คน เอ๊ยนั่งทำงานได้เต็มที่ 4 คนครับ
ท่านที่ใช้งาน NGINX คงจะคุ้นเคยกับการใส่ Certificate บน NGINX เพื่อที่เวลา Client request จะได้สามารถเปิด Connection แบบเข้ารหัสได้ ผลคือทำให้ Client สามารถเชื่อได้ว่าเป็นเว็บไซต์ เช่นเว็บผู้ให้บริการนี้ตัวจริง และยังช่วยเข้ารหัสข้อความที่ส่งไปมาระหว่างกัน
server {
listen 443 ssl;
server_name www.example.com;
ssl_certificate www.example.com.crt;
ssl_certificate_key www.example.com.key;
...
}
โดยปกติ Certificate จะถูกอ่านจากไฟล์(Disk) แล้วนำไปเก็บใน Memory ตอนที่ start NGINX ฉะนั้นการ Establish connection ก็จะเรียกใช้ key pairs ได้อย่างรวดเร็วผ่าน memory ถ้าเว็บมี server_name เดียว และไม่ได้เปลี่ยนคีย์บ่อยๆ หรือเปลี่ยนแบบมี Downtime ได้ การใช้งานแบบปกติก็ยังเพียงพอ
แต่ถ้าเป็นการที่มี Dynamic name เช่นมีหลายชื่อ มีชื่อเพิ่มเข้าออกบ่อย, หรือกรณีต้องการเปลี่ยน Certificate เป็นตัวใหม่ โดยไม่ให้เกิด Downtime กรณีนี้ เดิมทำได้ทั้งบน NGINX Plus และ NGINX OSS อยู่แล้ว ต่างกันที่วิธีการและ Performance
- โดย NGINX Plus ใช้ key-value store ในการเก็บ ซึ่งอยู่บน memory และ load ค่าใหม่จาก Disk เข้า Memory ได้หากต้องการ
- NGINX Open Source ใช้วิธีให้อ่านใหม่ทุกครั้ง ซึ่งมีผลกระทบคือเป็นการอ่านจาก Disk ทำให้กระทบกับ Performance กรณีที่ต้อง Establish connection บ่อยๆ
ที่จะเล่าวันนี้มาจาก SSL/TLS Certificate Rotation Without Restarts in NGINX Open Source โดยเป็นการใช้ความสามารถของ NGINX JavaScript Module มาทดแทน key-value store บน NGINX Plus
เริ่มจาก ให้ njs เป็นคนเก็บค่า certificate ไว้ใน Memory
# Sets an njs function for the variable. Returns a value of cert/key
js_set $dynamic_ssl_cert main.js_cert;
js_set $dynamic_ssl_key main.js_key;
จากนั้น NGINX นำค่านี้ไปใช้ตามปกติ ก็จะเป็นค่าอ่านค่า Certificate จาก Memory ซึ่งไม่กระทบกับ Performance แล้วนั่นเอง
# use variable's data
ssl_certificate data:$dynamic_ssl_cert;
ssl_certificate_key data:$dynamic_ssl_key;
เมื่อต้องการเปลี่ยนไปใช้ Certificate ใหม่ สามารถใช้ njs ให้ยกเลิกค่าใน Memory และไปอ่านค่าจากไฟล์ใหม่ได้ทันที, เมื่อ NGINX เรียกใช้ ก็จะเรียกใช้งานจาก Memory ได้ต่อเนื่อง
เบื้องหลังการยกเลิกการใช้งาน Certificate เดิมที่อยู่ใน Memory ให้ไป Load Certificate ใหม่จาก Disk
location = /clear {
js_content main.clear_cache;
# allow 127.0.0.1;
# deny all;
}
โดยสรุป เราสามารถที่จะใช้ NJS หรือ NGINX JavaScript Module ซึ่งใช้งานได้ง่ายด้วยภาษา JavaScript และคนทำเว็บคุ้นเคยอยู่แล้ว มาช่วยเพิ่มความสามารถอื่นๆ ให้ NGINX ได้ครับ ในทีนี้คือทำ Function Serve certificate จาก Cache พร้อมความสามารถในการ Reload Certificate ใหม่จาก Disk ลง Cache ได้ด้วยครับ __
Posted on September 29, 2023
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.