保護你的 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
平台,就可以安全的切換你的環墋變數。
希望我的推播(通知)功能正常