“Prevent Public Repos”を導入して、Public な Github リポジトリが作成されたら通知させる

Github

はじめに

お恥ずかしながら、Github 上の Organization 内に意図せずメンバが Public なリポジトリが作成されており、それに気づかないことがありました。

プロダクトコードをガシガシコミットされる前に気づけたのですが、「これは危ないな」と思い良い方法を探していたところ、 Github Apps に良さそうなアプリがあったので導入してみました。

検証環境

$ uname -moi
x86_64 MacBookPro16,1 Darwin

$ bash -version | head -n 1
GNU bash, version 5.1.8(1)-release (x86_64-apple-darwin20.3.0)

$ gh --version
gh version 1.10.2 (2021-05-19)
https://github.com/cli/cli/releases/tag/v1.10.2

"Prevent Public Repos" を利用する

以下の Github Apps が今回の用途にピッタリでした。

Public な Github リポジトリが作成されたタイミングで、Critical な Issue を作成してくれます。

Issue が作成されたことで気付けるのか?というのも含めて試してみます。

"Prevent Public Repos" 導入方法

1. Github Apps を追加

Prevent Public Repos のページ右上にある Add to Github ボタンをクリックします。

別ページに飛ぶため、インストールする際の Organization を 1 つ選択します。

App ページが表示されるので、 Get Started に書かれているとおりに進めていきます。

2. 管理用の Github リポジトリを作成

org-settings という名前で Organization リポジトリを新設することが推奨されているので、新しく作成します。

先程 Prevent Public Repos を追加した Organization にリポジトリを作成します。

Github の Web ページから作成してもいいのですが、コマンドライン操作に慣れているため、 gh コマンドを使ってコマンドラインから作成しました。

※ここでは Organization 名を仮に "MY_ORG" としています。

$ gh repo create --private MY_ORG/org-settings
? This will create the "MY_ORG/org-settings" repository on GitHub. Continue? Yes
✓ Created repository MY_ORG/org-settings on GitHub
? Create a local project directory for "MY_ORG/org-settings"? Yes
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in /tmp/work/org-settings/.git/
✓ Initialized repository in "org-settings"

3. "org-settings" リポジトリの作業用ディレクトリに移動

gh でリポジトリ作成するとローカル PC に Git 作業用ディレクトリが既にできているので、 cd して移動しておきます。

$ ls
org-settings

$ cd org-settings/

_もちろん、Web からリポジトリ作成した場合には git clone したあとに MARKDOWN_HASH6865aeb3a9ed28f9a79ec454b259e5d0MARKDOWNHASH していただければ同様の操作になります。

4. "org-settings" リポジトリに設定ファイルを追加

設定ファイルを .github/prevent-public-repos.yaml として作成します。

またまたコマンドラインでファイルを作成していますが、好きなエディタを開いてコンテンツを貼りつけても同じです。

$ mkdir -p .github/

$ cat <<'EOF' >.github/prevent-public-repos.yaml
# Configuration for Prevent-Public-Repos

# Turn on Monitor Mode. In this mode the repo visibility is not modified and only an Issue is created
monitorOnly: true

# Enables detection of repos that change visibility from private to public (not just newly created ones)
enablePrivateToPublic: false

# Issue Title when repo is privatized
privatizedIssueTitle: '[CRITICAL] Public Repositories are Disabled for this Org'

# Issue Body when repo is privatized
privatizedIssueBody: 'NOTE: Public Repos are disabled for this organization! Repository was automatically converted to a Private Repo. Please contact an admin to override.'

# Issue Title when monitor mode is enabled
monitorIssueTitle: '[CRITICAL] Public Repository Created'

# Issue Body when monitor mode is enable
monitorIssueBody: 'Please note that this repository is publicly visible to the internet!'

# Users/Groups that should be cc'ed on the issue. Should be users/groups separated by a space.
# ccList: '@user123 @user456'

# Repos to  exclude in detection. Should be a List of Strings.
# excludeRepos: ['repo1', 'repo2']
EOF

5. 設定ファイルを Push

Github リポジトリに push します。

$ git add .

$ git commit -m "first commit."
[master (root-commit) b856e5c] first commit.
 1 file changed, 25 insertions(+)
 create mode 100644 .github/prevent-public-repos.yaml

$ git push origin master
Enumerating objects: 4, done.
Counting objects: 100% (4/4), done.
Delta compression using up to 16 threads
Compressing objects: 100% (3/3), done.
Writing objects: 100% (4/4), 785 bytes | 785.00 KiB/s, done.
Total 4 (delta 0), reused 0 (delta 0), pack-reused 0
To github.com:MY_ORG/org-settings.git
 * [new branch]      master -> master

動作確認

それでは Public なリポジトリを作成し、検知されるかを確認してみます。

_度々ですが、 MARKDOWN_HASH19b19ffc30caef1c9376cd2982992a59MARKDOWNHASH コマンドを使って Github 上に公開リポジトリを作成していますが、Web 上から操作しても同じです。

$ gh repo create --public MY_ORG/invalid-public-repo-sample
? This will create the "MY_ORG/invalid-public-repo-sample" repository on GitHub. Continue? Yes
✓ Created repository MY_ORG/invalid-public-repo-sample on GitHub
? Create a local project directory for "MY_ORG/invalid-public-repo-sample"? Yes
hint: Using 'master' as the name for the initial branch. This default branch name
hint: is subject to change. To configure the initial branch name to use in all
hint: of your new repositories, which will suppress this warning, call:
hint:
hint:   git config --global init.defaultBranch <name>
hint:
hint: Names commonly chosen instead of 'master' are 'main', 'trunk' and
hint: 'development'. The just-created branch can be renamed via this command:
hint:
hint:   git branch -m <name>
Initialized empty Git repository in /private/tmp/work/invalid-public-repo-sample/.git/
✓ Initialized repository in "invalid-public-repo-sample"

作成された直後に、僕のメールアドレスに通知が飛びました。

Issue の中に @genzouw という文字が見えました。
リポジトリ作成者にメンションしているため、通知が行われたようです。

最後に不要になったリポジトリを削除しましょう。
コマンドラインから...といきたところですが、2021-05-21時点では gh コマンドでリポジトリを削除することはできないようなので以下のコマンドでGithubページを開いて手作業で。

$ gh repo view --web

gh コマンドにリポジトリ削除機能を入れる話はIssueとして上がっているようです。

危険なコマンドではあるので、導入に慎重になったというのもわかります。

ひとこと

Issue と飛んてきた通知メールを無視されてしまった場合のリスクもありますが、取り急ぎ最低限のコストでリスクを潰しておきました。

Github