眾所周知,版本控制系統會將所有的變更都存起來,因此我們能夠隨意回溯到任一版本,這些變更也包含你不小心提交存有機密資料的檔案,或是帳號密碼等字串。
對於版本控制不熟的使用者來說,可能會以為再提交 1 個已經刪除機敏資料的 commit 就安全了,實則不然,有心人士依然可以透過回溯版本或者在 .git
版本控制系統的資料夾內用工具撈出各種疑似帳號密碼的字串,進而入侵你的系統。
實際上也確實有數起資安事故是由於版本控制系統中含有帳號密碼等資訊所造成。
所以要從清理機敏資料,一定要連版本控制系統內的變動紀錄都要一併清理才安全!
本文將教導如何以 bfg 指令安全地清除含有密碼、金鑰等機敏資料的 commits 。
本文環境
- macOS
- BFG Repo-Cleaner
$ brew install bfg
bfg repo-cleaner
BFG Repo-Cleaner 是 1 套專門用來清理 Git 的工具,是 git-filter-branch 的替代工具,速度比起 git-filter-branch 快上 10 到 720 倍,而且使用上更為簡單、直覺,是值得推薦的好工具!
清除含有機密資料的檔案與相關 commits
假設你不小心把機密檔案 secret.json
給 commit 了,例如下列資料夾結構:
.
├── credentials
│ └── secret.json
└── .git
要用 bfg 指令刪除機密檔案的 commits 的話,只要使用 --delete-files
參數並指定路徑與檔案名稱即可(注意,一定要用單引號或雙引號將路徑檔名包起來,因為 bfg 會到 .git
中尋找所有符合的檔名並刪除相關 commit :
$ bfg --delete-files 'credentials/secret.json'
bfg 也支援 *
米字號作為萬用字元,可以一併刪除符合 pattern 的檔案的 commits, 例如下列指令刪除 credentials/
資料夾底下所有 .json
檔的所有 commits:
$ bfg --delete-files 'credentials/*.json'
bfg 刪除完相關 commit 之後,還需要執行以下指令將 .git
資料夾中相關檔案真正地從檔案系統中刪除,才算完成:
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
最後將 repo push 回 remote, 蓋掉原本的 .git
:
$ git push
怎麼最新的 commit 還是有機密檔案存在?
有人可能會遇到執行 git push
之後,在本地與遠端的 repo 都還是可以看到該機密檔案存在,這是由於 bfg 預設會保護 main/master 分支最新的 commit (也就是 HEAD), 因此不做任何清理,這是由於 main/master 分支最新的 commit 通常跟 production 環境有關, bfg 怕修改之後會影響到 production 環境,所以特別設定保護機制。
要關掉 bfg 預設保護機制的話,只要加上 --no-blob-protection
參數即可,例如:
$ bfg --delete-files 'credentials/*.json' --no-blob-protection
清除含有機密資料的字串與相關 commits
除了刪除機密檔案之外,另 1 種常見的情況是帳號、密碼、 API keys 等字串不小心被 commit 進版本控制系統,這時同樣可以使用 bfg 指令進行清理。
你可以將要清理的帳號、密碼、 API keys 等資料放到 passwords.txt
文字檔內, 1 行 1 個字串,例如:
the_password
123456789
接著,用 --replace-text
參數以及指定以剛剛的 passwords.txt
, bfg 會自動找尋所有的 commits 是否含有 passwords.txt
內的字串,並進行清理:
$ bfg --replace-text passwords.txt
被清理的字串會被字串 ***REMOVED***
取代。
最後同樣執行以下指令清理檔案並 push back:
$ git reflog expire --expire=now --all && git gc --prune=now --aggressive
$ git push
–no-blob-protection 保護
--replace-text
同樣也會有針對 main/master 分支最新的 commit 的保護機制,要關掉保護機制的話,同樣加上 --no-blob-protection
參數即可:
$ bfg --replace-text passwords.txt --no-blob-protection
總結
不小心將機敏資料 commit 是常有之事,為避免機密資料存在版本控制系統之中造成隱患,使用 bfg 等工具進行清理是相當重要的工作。
另外, bfg 不只可以清理機密資料、檔案,也可以用來清理大檔案,避免 Git repo 越長越大,是相當實用的工具!
以上!
Happy Coding!
References
https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/removing-sensitive-data-from-a-repository