t-hom’s diary

主にVBAネタを扱っているブログです。

GitHubに誤って自宅WiFiパスワードをPushしてしまったので対処した件

GitHubを使い始めた背景

最近、Raspberry PiやM5 Stackでの開発が本格化してきたため、レガシーなファイル名によるバージョン管理では限界が来ている。
ラズパイの本番機は先日綺麗にしたのだが、開発機はこのありさま。。
f:id:t-hom:20210227132729p:plain

ステージング用に準備したフォルダの筈が、面倒くさくなってVNC接続してそのままVimで色々と作り始めた次第。
完全にworkフォルダの二の舞に。。

ちなみにworkフォルダの様子。。もう何のプロジェクト用だったか分からないファイルが沢山。
f:id:t-hom:20210227132917p:plain

いい加減Gitで管理しようということで、再入門してみた。
※個人のVBAプロジェクトで見よう見まねで使ったことはあるが、書籍を通しで読んで本格的にやるのは初めて。

購入したのはこちらの書籍。

わかばちゃんと学ぶ Git使い方入門

わかばちゃんと学ぶ Git使い方入門

一切コマンドが登場せず、SourceTreeというGuiツールのみで解説されているので、操作の種類や概念を学ぶのにとても良い。
ただし、記載内容はやや古く、SourceTreeの導入部分と、GitHubのプライベートリポジトリが有料という記載は現在は当てはまらない。

トラブル発生

さくっと読了して早速Raspberry PiとM5 StackのプロジェクトをGitHubにPushしたのだが。。。
そこで凡ミス発生。

M5 Stack用のソースコードにssidとpasswordが記載された状態でそのままアップロードしてしまったのだ。

Gitはバージョン管理システムなので、普通に消しても履歴上は残ってしまう。つまり過去履歴をたどるとssidとpasswordが出てきてしまう。
今回はPrivateリポジトリにしていたので他人に見られることは無くてセーフなんだけど、Publicにしてたらと思うとゾッとするミスである。

履歴の削除対応

履歴の削除は次のように行うようだ。結局コマンドが必要になる。
docs.github.com

なお、記載されているBFG は今ひとつ使い方が分からなかったので、filter-branch を使用することにした。
書かれている手順でやったことは次のとおり。

1) 機密データを含むリポジトリのローカルコピーが履歴にまだない場合は、ローカルコンピュータにリポジトリのクローンを作成します。

ローカルで作業してるのでクローンする必要はないかと思ったけど、指示と違うことをやってしまうと怖いので、現在Source Treeで作業しているフォルダーとは違う場所にフォルダーを作って、GitHubからCloneした。

2) リポジトリのワーキングディレクトリに移動します。

そのとおり作業

3) 次のコマンドを実行します。機密データを含むファイルへのパスは、ファイル名だけではなく、削除するファイルへのパスで置き換えます。

コマンドが示されているが、Unix/Linuxに慣れてないと意味が分からんと思う。GitHub使う時点で慣れてる前提かな。
とりあえず補足しておいた。
f:id:t-hom:20210227135815p:plain

それから、PATH-TO-YOUR-FILE-WITH-SENSITIVE-DATAは削除したいファイルのパスに置き換えるらしいんだけど、「パス」って何のパスなのかも初心者には辛いところ。

GitHub上にパスがあればコピーしてくれば良いんだけど、ここでは消したいファイルを削除してコミットした前提でたどり方を説明する。なお、私の環境では本当に消したいファイルは既に消したあとなので、このあとの説明は適当なファイルを例に挙げている。

過去に消したファイルには、コミット履歴から辿れるので、まずはコミットログを開く。
f:id:t-hom:20210227140545p:plain

ファイルを削除する前のコミット履歴を開く
f:id:t-hom:20210227140833p:plain

Browse Fileをクリック
f:id:t-hom:20210227141016p:plain

特定の履歴に飛ぶのでフォルダーから消したいファイルまでたどる。
f:id:t-hom:20210227141232p:plain

ファイルを開いたらメニューからCopy Pathでクリップボードに値がコピーされる。
f:id:t-hom:20210227141604p:plain

あとはコマンドのPATH-TO-YOUR-FILE-WITH-SENSITIVE-DATAの部分をコピーしたパスに置き換える。
例えばcalorie_graph.pyを履歴から削除したい場合は次のコマンドになる。改行せずに1行で入力しきったのでバックスラッシュはない。

git filter-branch --force --index-filter "git rm --cached --ignore-unmatch pi/m5_visualizer/calorie_graph.py" --prune-empty --tag-name-filter cat -- --all

4) 機密データを含むファイルを、誤って再度コミットしないようにするため、.gitignore に追加します。

その通り対応。
YOUR-FILE-WITH-SENSITIVE-DATAをファイル名に置き換える。これはパスじゃなくて単にファイル名でOK。

5) リポジトリの履歴から削除対象をすべて削除したこと、すべてのブランチがチェックアウトされたことをダブルチェックします。

具体的にどうするのか分からなかったのでやってない。要は確認なので、所詮情報の消し漏れで困るのは私ひとりの為、この項目はスキップした。業務で対応してる方はちゃんと調べるなり、サポートに問い合わせるなりしないとまずいと思う。

6) リポジトリの状態が整ったら、ローカルでの変更をフォースプッシュして、GitHub リポジトリと、プッシュしたすべてのブランチに上書きします。

その通り対応。

7) 機密データをタグ付きリリースから削除するため、Git タグに対しても次のようにフォースプッシュする必要があります。

その通り対応したが、結果は「すでに対応済」のようなメッセージが出て特に何も起こらなかった。

8) GitHub Support or GitHub Premium Support に連絡し、GitHub 上で、キャッシュされているビューと、プルリクエストでの機密データへの参照を削除するよう依頼します。

その通り対応。ここまでの操作ログを張り付けて、前述のページに従って作業したのでキャッシュ削除して欲しい旨を英語で連絡した。返事待ち。

9) コラボレータには、 作成したブランチを古い (汚染された) リポジトリ履歴からリベースする (マージしない) よう伝えます。 マージコミットを 1 回でも行うと、パージで問題が発生したばかりの汚染された履歴の一部または全部が再導入されてしまいます。

具体的にどうすれば良いのか不明で私ひとりの開発なので、この作業の代わりにSourceTreeで使っていたローカルのファイルをすべて削除したうえ、GitHubから新たにプロジェクトをクローンしてきてそちらを正とした。

10) 一定の時間が経過し、git filter-branch に意図しない副作用がないことが確信できるようになったら、次のコマンドによって、ローカルリポジトリのすべてのオブジェクトが強制的に参照から外されガベージコレクトされるようにします (Git 1.8.5 以降を使用)。

これもよく分からないので特に何もしてない。
恐らくGitHubからクローンしなおしてるので問題ないと思う。

以上で履歴の削除対応は完了とした。
繰り返しになるが、仕事に使ってる方や完全削除しないと他人に迷惑のかかるデータを消す場合は、サポートに問い合わせをしてでも作業を完遂したことを確認すべきだと思う。

私の場合は最悪自分しか困らないシチュエーションだったのである程度緩い対応で済ませたが、真似して痛い目を見ても責任は負いかねるのであしからず。

再発防止

Wi-Fi接続用のSSIDとパスワード情報を他のファイルに分離することにした。
ありがたいことに以下のサイトで実例を見つけたので真似してやってみた。
scrapbox.io

ライブラリフォルダってどこなのか一瞬分からなかったので備忘録としてスクショ張っておく。
f:id:t-hom:20210227143535p:plain

このヘッダーのコードは参照先サイトと同じく、そのまま。
f:id:t-hom:20210227143757p:plain

前述の場所に置いておくとスケッチメニューからライブラリのインクルードでssid_defineが見つかるので、メインコードを開いた状態でそれをクリックすると、include文がコードの先頭に追記される。
参照先サイトではdefine文でssid_defineを取り込むような表記になってたけど、エラーになったので多分記載ミスだと思う。

あとはこんな感じでメインコードからMY_SSIDとMY_SSID_PASSを参照できるようになる。

#include <ssid_define.h>
#include <M5Stack.h>
#include <WiFi.h>

int p;
int digit[4];

const char* ssid     = MY_SSID;
const char* password = MY_SSID_PASS;

//以下略

これでこのコードをGitHubにアップロードしてもパスワード流出の危険はなくなった。

終わりに

今回はPrivateリポジトリで発生したミスなので流出の危険性は低く、しかも自分の自宅Wifiパスワードなので万が一流出しても困るのは私だけ、また所詮電波の届く範囲からしか接続されることはないのでリスクはほとんど無いようなものである。

だからじっくり対応できたしこの程度の対応で済ませたんだけど、もしこれが公開リポジトリで、他人の個人情報や公開サービスのパスワードなんてことになったら目も当てられない。

なので、GitHub使い始めたばかりの方はこういう凡ミスを起こしたときに焦らず確実に対処できるように、問題のないファイルを使って履歴削除の練習をしておくと良いと思う。
※サポートへのキャッシュ削除依頼は、本当に削除が必要な場合以外はしないでください。

以上。ああ、疲れた。

2/28 追記

GitHub Supportから返信が来てサーバー側のキャッシュをクリアしてくれたので追記。

私がサポートに送った内容全文

メールではなくてWebからの問い合わせとなる。markdown記法が使えるので#が付いてるのは見出し。
依頼事項と対照リポジトリ/ファイル/操作内容をコマンドプロンプトから貼り付けておいた。
コマンドと結果が分かりづらいのでコマンドだけ赤色にしておいた。

このときはmainブランチしかなかったので特にブランチ指定はしてないけど、複数ブランチに消したいファイルがあれば伝えた方が良いのかもしれない。
ただ後述する返信を見るとリポジトリに対してガベージコレクションをかけただけっぽいのでそんなに細かい内容を送らなくても良かったのかも。
まぁ送って間違いはないと思う。何か間違ってることがあればついでに指摘してくれるだろうし。

Dear Person in Charge,


Sorry to bother you. I wrongly pushed a file which include Wi-Fi password to my repository.
I've finished step 7 of following instruction.
https://docs.github.com/en/github/authenticating-to-github/removing-sensitive-data-from-a-repository#purging-a-file-from-your-repositorys-history


Could you please remove cached view?


Note: please tell me if I'm asking something wrong. I'm almost newbie for Git.

# Repository(Private)

https://github.com/thom-jp/health-tracking-pi

# Removal Target

m5/client/client.ino

# Removal Operation Log

Microsoft Windows [Version 10.0.19041.804]
(c) 2020 Microsoft Corporation. All rights reserved.

C:\Users\ho_>cd OneDrive\dev\htp

C:\Users\ho_\OneDrive\dev\htp>git clone https://github.com/thom-jp/health-tracking-pi
Cloning into 'health-tracking-pi'...
remote: Enumerating objects: 71, done.
remote: Counting objects: 100% (71/71), done.
remote: Compressing objects: 100% (67/67), done.
remote: Total 71 (delta 5), reused 63 (delta 1), pack-reused 0
Receiving objects: 100% (71/71), 705.90 KiB | 966.00 KiB/s, done.
Resolving deltas: 100% (5/5), done.

C:\Users\ho_\OneDrive\dev\htp>cd health-tracking-pi

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>git filter-branch --force --index-filter "git rm --cached --ignore-unmatch m5/client/client.ino" --prune-empty --tag-name-filter cat -- --all
WARNING: git-filter-branch has a glut of gotchas generating mangled history
rewrites. Hit Ctrl-C before proceeding to abort, then use an
alternative filtering tool such as 'git filter-repo'
(https://github.com/newren/git-filter-repo/) instead. See the
filter-branch manual page for more details; to squelch this warning,
set FILTER_BRANCH_SQUELCH_WARNING=1.
Proceeding with filter-branch...

Rewrite 31f5c3bed9103b44a88e1111f3d63b26d6279447 (5/7) (3 seconds passed, remaining 1 predicted) rm 'm5/client/client.ino'
Rewrite 4c74c75abb9cea3100de7586e183411f9ae0eebd (7/7) (4 seconds passed, remaining 0 predicted)
Ref 'refs/heads/main' was rewritten
Ref 'refs/remotes/origin/main' was rewritten
WARNING: Ref 'refs/remotes/origin/main' is unchanged

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>echo "m5/client/client.ino" >> .gitignore

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>git add .gitignore

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>git commit -m "Add client.ino to .gitignore"
[main c945e1d] Add client.ino to .gitignore
1 file changed, 1 insertion(+)
create mode 100644 .gitignore

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>git push origin --force --all
Enumerating objects: 69, done.
Counting objects: 100% (69/69), done.
Delta compression using up to 6 threads
Compressing objects: 100% (64/64), done.
Writing objects: 100% (69/69), 704.03 KiB | 140.81 MiB/s, done.
Total 69 (delta 5), reused 60 (delta 3), pack-reused 0
remote: Resolving deltas: 100% (5/5), done.
To https://github.com/thom-jp/health-tracking-pi

- 4c74c75...c945e1d main -> main (forced update)

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>git push origin --force --tags
Everything up-to-date

C:\Users\ho_\OneDrive\dev\htp\health-tracking-pi>

GitHubサポートからの返信メール

Thanks for reaching out! I've run a garbage collection and cleared our cached views for `thom-jp/health-tracking-pi`, so any sensitive data removed should no longer be accessible on GitHub.
If there are any remaining commits with sensitive data in them, you can send us the SHAs and we can check where else those commits might still be referenced. Otherwise, feel free to let us know if there's anything else we can assist you with!

お礼の返信もしておいた

I really appreciate for your prompt action.
Wishing you all the success in your future endeavors.

Sincerely Yours,
Thom

私もヘルプデスクで働いた経験があるが、丁寧にお礼を言ってくれるユーザーは意外と覚えているもので、次回の対応は率先して行うようになる。チームで対応してるのでSLAのファーストレスポンスギリギリまで取らない案件と、率先してピックアップされる案件がある。だって丁寧なユーザーでさっさと自分の手を埋めてしまったほうが横柄なユーザーが他のスタッフに回るし。Hahaha.

当ブログは、amazon.co.jpを宣伝しリンクすることによってサイトが紹介料を獲得できる手段を提供することを目的に設定されたアフィリエイト宣伝プログラムである、 Amazonアソシエイト・プログラムの参加者です。