保護你的 Environment Variables
tags: Env CI
category: DevOps
description: 保護你的 Environment Variables
created_at: 2024/11/08 11:00:00

前言
昨天剛把部落格的推播(通知)功能完成,所以今天就先快速記錄一篇文章來做實驗推播給自己,所以這一篇內容也會比較輕鬆一些。不會那麼燒腦
這一篇要記錄的是如何保護環境變數(?),通常環境變數會放一些比較敏感的資訊,例如 API Key 或是 DB Password 等等,雖然也可以放一些共用的東西來方便抽換,這些資訊通常會不希望被拿走,所以通常都會有一些處理方式。
這篇主要是使用 .env 的方式。
預備知識
- 你應該知道什麼是環境變數 (
廢話 - 你用過
.env檔案: 因為這篇使用.env介紹 - 認識
JavaScript或是Node.js: 因為這篇會用Node.js來做範例 Windows可能需要WSL去幫助你執行相關指令
建立 .env 檔案
首先我們先建立一個 .env 檔案,這個檔案通常會放在專案的根目錄下,這個檔案會放一些環境變數,例如:
API_KEY=123456
嗯..非常陽春,反正只是當範例用,所以就隨便放一個 API_KEY 進去。
讀取 .env 檔案
這邊使用 dotenv 這個套件來讀取 .env 檔案。
首先先安裝 dotenv:
$ npm install dotenv
然後在你的程式碼中引入 dotenv:
require('dotenv').config()
這樣就可以讀取 .env 檔案了。
console.log(process.env.API_KEY)
然後去執行你的程式碼,你應該會看到 123456 這個值。
就這樣?
如果只是這樣的話標題應該不會是「保護你的 Environment Variables」,因為這樣的話就只是把敏感資訊放在 .env 檔案中,但是這樣的話還是有一些問題,例如:
- 被拿走就看光光了(?): 不管任何拿法,直接拿檔案或是傳訊息
CI平台有可能會有漏洞,導致你的環境變數被拿走,這時如果你的環境變數是放機密資訊的話就很危險
所以這時我們需要的是讓 .env 被拿走也沒關係的解決方案;或是說最終部署就不要採 .env 了,也許 .env 就讓你在 local 開發時方便使用即可。
這時可以使用一個套件 dotenv-vault 來幫助我們。
使用 dotenv-vault
這個套件有支援 cloud 版本,但是 cloud 版本需要登入(也有付費版),而對於自己日常開發用的話我不太喜歡登入(送個資),所以這邊只會介紹 local 版本,也很方便。
就以剛才的範例延續,我們直接在專案中執行 build 指令:
$ npx dotenv-vault local build
這時你會看到根目錄下多了兩個檔案,分別是
.env.vault: 這個檔案是加密過的.env檔案,這個檔案可以上版控.env.keys: 這個檔案是解密用的金鑰: 這個檔案不要上版控,如果你用CI平台,就放對應的Secrets中即可- 但剛剛不是說不要放機密資訊嗎? 這個檔案只是用來解密
.env.vault的,攻擊者只拿的到你的環境變數(key),沒有你的.env.vault也沒用。
- 但剛剛不是說不要放機密資訊嗎? 這個檔案只是用來解密
這時你可以先做個實驗,把 .env 刪除,然後再執行你的程式碼,你會發現程式碼輸出變成 undefined 了。
這時來看看怎麼把原來的環境變數倒入你的程式中:
所以依照剛才說的,用 key 來解密,所以先把你的 key 複製好(假設我複製的 key 叫做 <key>):
$ DOTENV_KEY=<key> command
嗯.. 可能需要一點想像,所以再做個假設,我的程式碼是 main.js,那麼:
$ DOTENV_KEY=<key> node main.js
這樣你就會又看到了 123456 這個值。
然後如果你想要取得原本的 .env 檔案,可以使用:
$ npx dotenv-vault local decrypt <key>
這樣就會看到輸出原本的 .env 檔案。
API_KEY=123456
一點小細節
在一開始執行 build 指令時,會看到一個 DEPRECATED 的訊息(雖然不知道未來還在不在),總之是作者希望你改用 dotenvx 的方式做加密,所以這裡也提一下。
使用 dotenvx
這邊一樣使用前面的 .env 內容,但是這次使用 dotenvx 來做加密。
這時指令變成了:
$ npx @dotenvx/dotenvx encrypt -f .env
然後你會看到你的 .env 內容直接被加密了,然後目錄下也多了一個 .env.keys 檔案。
接著如果你直接執行你的程式碼,他的值會是加密過的東西,沒辦法使用,所以要使用 dotenvx 的執行方式:
$ npx @dotenvx/dotenvx run -f .env -- node main.js
這樣你就可以看到 123456 這個值了。
然後版控的邏輯和剛才一樣:
.env.keys不要上版控.env可以上版控,因為已經被加密過了
簡單的 POC 要這麼麻煩嗎?
當然是不用啊廢話,甚至你的 .env 根本沒有敏感資訊你要推上版控也不是不行,工具總是用來解決問題的,如果你的問題不是這個,那當然不用這麼麻煩。
那幹嘛要有這一個小節?
嗯.. 因為我想順便介紹說 nodejs 的 20 版本之後新增了 --env-file 的參數,如果只是做簡單的 POC 之類的小東西也滿方便的 (當然他有些不足的地方,期望未來變得更好)
用法非常簡單,這樣你連 dotenv 都不用了: (記得把 require('dotenv').config() 移除)
$ node --env-file=.env main.js
你一樣會看到 123456 這個值。
而且這樣 Windows 也解脫了
結論
這篇文章主要是介紹如何保護你的環境變數,這樣的話就不用擔心環境變數被拿走,然後可以接著整合 CI 平台,就可以安全的切換你的環墋變數。
希望我的推播(通知)功能正常