カテゴリー
【GitHub活用メモ】GitHubの認証をSSH接続方式にしてみる(Dockerコンテナ対応済)
※ 当ページには【広告/PR】を含む場合があります。
2021/02/16
2023/08/25

去年の暮れに
よって、普段GitHub上で開発作業を行っているユーザーは
パスワードを用いた一切のGitHub上のレポジトリアクセスができなくなるので、一部のパスワードを直接送信していたgit操作のコマンドやデスクトップアプリなどに影響があるようです。
これまで日常的にhttps/ssh接続で作業してこられた方には影響はないものと思います。
とはいえ、GitHubでも2段階ファクター認証などをメールなどで催促されるなど、昨今ではセキュリティー強化の流れもあります。
今回の記事では、弊社のアカウントでSSH接続させて利用する方法を試したときのメモとして残しておこうと思います。
一般OS編〜GitHubによるSSH接続
では早速SSH接続からGitHubアカウントを利用するための手順を見ていきます。
ed25519暗号のSSHキーを生成する
sshの暗号方式で、もっともメジャーなのが
rsa
ed25519
ということで今回はed25519方式で公開鍵と秘密鍵のペアを生成してみます。
生成コマンドを実行すると、
鍵の名前 > パスフレーズ > パスフレーズ(確認)
何も入力せずにEnterを押してもデフォルト値の
id_ed25519.pub(公開鍵)
id_ed25519(秘密鍵)
鍵が複数必要な場合には、鍵の名前を与えずに生成の操作を繰り返すと、直前に生成していたid_ed25519という名前の秘密鍵が上書きされてしましますので、適当な名前を付けて生成する必要があります。
#👇-Cオプションでコメントが付けられます
$ ssh-keygen -t ed25519 -C 'tacoskingdom'
Generating public/private ed25519 key pair.
Enter file in which to save the key (/home/*******/.ssh/id_ed25519):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/*******/.ssh/id_ed25519.
Your public key has been saved in /home/*******/.ssh/id_ed25519.pub.
The key fingerprint is:
SHA256:******************************************* tacoskingdom
The key's randomart image is:
+--[ED25519 256]--+
#以下略
ここでの
「パスフレーズ」
一人で使うレポジトリのために、わざわざgitコマンド一回ごとにパスワードを聞かれるのも面倒と感じる場合には、パスフレーズを空にしておくのも良いと思います。
GitHubに公開鍵を設定する
さて、生成した公開鍵と秘密鍵のペアでそのままでもssh接続することができます。
"pub"と付いている方の公開鍵(
id_ed25519.pub
他方、"pub"の付いていない秘密鍵の方を自分や秘密を保持させたいチームの内部で利用する流れになります。
当然GitHubにアクセスするときに、この秘密鍵をもっていないとアクセス出来ませんので、失くさないように管理・運用方法なども事前に取り決めを作っておくことも必要です。
ではこの公開鍵(
id_ed25519.pub
さきほど生成した公開鍵の中身をcatで確認します。
$ cat ~/.ssh/id_ed25519.pub
ssh-ed25519 A***********************************************************h tacoskingdom
なんだかズラズラーっと表示されている中程の文字が公開鍵の中身だと思われます。
これを以下の図のように、Gitgubページのアイコンから
[Settings] > [SSH and GPG keys] > [New SSH key] > Key値の設定 > [Add SSH key]

これで
[Add SSH key]
ではこの公開鍵
id_ed25519.pub
id_ed25519
$ ssh -T git@github.com
The authenticity of host 'github.com (xx.xxxx.xx.xx)' can't be established.
RSA key fingerprint is SHA256:n***********************************8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,xx.xxxx.xx.xx' (RSA) to the list of known hosts.
Hi tacoskingdom! You've successfully authenticated, but GitHub does not provide shell access.
ということで、どうやらGitHub側にSSH接続が成功したようです。
複数のSSHキーを管理するときの注意点
なお、複数のSSHキーがローカルに存在していた場合、システムはデフォルトでどの鍵を使えばいいのか分からないので、使う鍵を教えてあげないと利用できません。
ということで
~/.ssh/config
$ nano ~/.ssh/config
#👇ホストがgithub.comの場合
Host github.com
HostName github.com
User git
IdentityFile "~/.ssh/id_ed25519"
複数のGitHubアカウントでSSHキーを割り当てて管理する場合の設定の書き方は
簡単なgit操作
後はもうここまで設定できたらいつものgit操作でレポジトリにアクセス可能です。
あとは何か新しいレポジトリのプロジェクトを作成したときに現れる以下のような手順をヒントに作業を進めていくと良いでしょう。

Dockerコンテナ編〜GitHubによるSSH接続
先程の内容までは、Gitとsshコマンドの使えるOS環境であればおそらく同じように動作するSSH接続方式のGitHub認証のやり方を解説しました。
ここからは、Dockerコンテナの内部からインタラクティブモードなどでソースコード開発を進めていく際に便利な設定を構築する手法を紹介します。
例えば開発用のDockerコンテナ内でのコーディング作業を終えたら、一旦ホストOSに戻り、その差分をコミットし、プルリクエストを送る、というように逐一Dockerコンテナ入ったり出たりするスタイルの開発方法をやっていると、たまに切り替えるのが面倒になったりします。
ホストで使ってるSSH認証キーをそのままDockerコンテナでも利用できるようにすることで、Dockerコンテナ内からでもGitHubレポジトリにアクセス出来るようなります。
ホストからDockerコンテナーへのSSH認証キーの受け渡しは以下の図のように主に2通り方法があります。

このやり方には、複数のSSHキーを所有しているホストOSのGit環境であっても、Dockerコンテナに渡す鍵をどれか一つに限定することで、コンテナとレポジトリを一対一対応にさせることが出来ます。
これはGitHubアカウントを複数持っている場合、ホストOSはSSH鍵の保有と管理に注力して、開発時にはDockerコンテナを使い分けるだけでGitHub上のレポジトリを適切に割り当てることができるので、セキュリティを扱っている人間としては少し気持ちが楽になります。
この記事を見て頂いている方の中にはいらっしゃらないと思いますが、開発中のプロジェクト内にSSH認証キーごとファイルに含めてしまって、そのまま気づかすにGitHubレポジトリへ上げてしまった...という恐ろしい話もあります。
やってしまう人のほとんどが入社間もなくSSHやGitの経験も浅い開発者の方がほとんどかと思いますが、それはプロジェクトの開発責任者が予め教育すべきだったミスによるものです。
SSH認証キーがレポジトリ上に晒しておくのは、家の鍵を玄関のドアに挿したままにしておく位危険ですので、チームによって開発を進めていく際には必ず管理方法を見直しておきましょう。
ここでは
DockerfileのCOPY(ADD)でSSH認証キーを埋め込む
まず一つ目のパターンのDockerfileにCOPY(ADD)で秘密鍵を埋め込むやり方を検討します。
Dockerfileを作成する前にまずCOPYとADDのホスト側へのアクセス権限から説明します。
結論からいうと、
COPY [ホスト側Dockerfileのあるディレクトリからの相対パス] [コンテナ側の絶対パス]
これはセキュリティ上の理由ですので、ホスト側のファイルを自由に読み込めないのはちょっと面倒ですが、Dockerfileと同一階層か、それより下層の見える位置に秘密鍵を持ってこないとCOPY出来ません。
ということで現在のプロジェクトには以下のように.sshファイルをハードコピーして利用します。
.
├── Dockerfile
├── docker-compose.yml
├── .gitignore
└── .ssh
└── id_ed25519
この場合、秘密鍵をうっかりGitHub側へ上げてしまわないように
.gitignore
#👇追加
/.ssh
とするとSSH認証キーはレポジトリに含まれなくなります。
では、必要最低限のalpineコンテナを以下のような
Dockerfile
FROM alpine:3.18
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
#👇Dockerコンテナの作業ルートディレクトリ(今回は'/usr/src/app/')へ秘密鍵をコピー
WORKDIR /usr/src/app/
COPY .ssh/ /usr/src/app/.ssh
CMD ["bash"]
通例として、SSHクライアント固有のSSH認証情報は、このユーザーのホームディレクトリ(
~/.ssh/
Dockerコマンドのオプションを手で打つのは面倒ですので、以下のようにdocker-composeを利用します。
docker-compose.yml
version: '3.9'
services:
app:
image: my-app-dev:alpine3.18
build: .
container_name: my-app-dev
working_dir: "/usr/src/app"
tty: true
このDockerイメージをローカルビルドし、コンテナを立ち上げ、端末からインタラクティブモードにアタッチしてみます。
$ docker-compose build
$ docker-compose up -d
$ docker-compose exec app bash
#...インタラクティブモードでコンテナに入る
$ ls -la | grep .ssh
drwxr-xr-x 2 1000 1000 4096 Jan 26 01:48 .ssh
$ ls -la .ssh
total 12
-rw------- 1 1000 1000 399 Jan 26 01:48 id_ed25519
でもこれだと、ただ秘密鍵だけが作業ディレクトリに入っているだけで、プロジェクト開発に必要な他の具材がコンテナに入っていません。
そこで
docker-compose.yml
version: '3.9'
volumes:
#別のダミーボリュームを準備
ssh_key:
services:
app:
image: my-app-dev:alpine3.18
build: .
container_name: my-app-dev
volumes:
- ./:/usr/src/app
#👇秘密鍵だけダミーへマウント
- ssh_key:/usr/src/app/.ssh
working_dir: "/usr/src/app"
tty: true
これで見た目は代わりませんが、一応ホストとコンテナとのSSH認証キーとの独立性を保ちながら、他のリソースはコンテナへマウントすることが出来るようになります。
なお、Dockerコンテナを起動する際にvolumeオプションから、
.ssh
とは言え、秘密鍵への意図しない書き込みで壊れるのをそんなに気にしても仕方ない、とさほど気にする必要もないなら、端から
Dockerfile
やり方としては以下のように
Dockerfile
docker-compose.yml
FROM alpine:3.18
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
CMD ["bash"]
version: '3.9'
services:
app:
image: my-app-dev:alpine3.18
build: .
container_name: my-app-dev
volumes:
- ./:/usr/src/app
working_dir: "/usr/src/app"
tty: true
...
.ssh
とにかく秘密鍵をコンテナ側に埋め込みましたので、この状態でまずGitHubとの接続状態を確認しましょう。
コンテナが最初に立ち上がる場合には、初回はssh-agentが立ち上がっていませんので、evalコマンドからプロセスID指定で立ち上げる必要があります。
※面倒なら起動デーモン用の設定ファイルを仕込むか、
.bashrc
$ eval "$(ssh-agent)"
Agent pid 16
$ ssh-add .ssh/id_ed25519
Identity added: .ssh/id_ed25519 (tacoskingdom)
$ ssh -T git@github.com
The authenticity of host 'github.com (xx.xxxx.xx.xx)' can't be established.
RSA key fingerprint is SHA256:n***********************************8.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'github.com,xx.xxxx.xx.xx' (RSA) to the list of known hosts.
Hi tacoskingdom! You've successfully authenticated, but GitHub does not provide shell access.
...素晴らしい。
これでDockerコンテナからでもGitHubへのログイン認証が完了しました。
Dockerfileで秘密鍵をCOPYするだけですが、簡単にGitHubが操作できるようになります。
ただこのやり方での注意はビルド済みのDockerイメージにSSH認証キーが埋め込まれるため、Publicに向けてDockerHubで公開することは出来ません。
もしもDockerイメージごと開発環境として公開したい場合には、次に説明する
docker cp
docker cpサブコマンドでSSH認証キーをコンテナに送る
こちらも具体的にやってみましょう。
先ほどの
Dockerfile
FROM alpine:3.18
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
CMD ["bash"]
また
docker-compose.yml
.ssh
volumes
[マウント元のホスト側のフォルダ]:
cp /dev/null
version: '3.9'
services:
app:
image: my-app-dev:alpine3.18
build: .
container_name: my-app-dev
volumes:
- ./:/usr/src/app
#exclude files in volume
- /usr/src/app/.ssh
working_dir: "/usr/src/app"
tty: true
再びイメージをビルドして、コンテナを起動し、インタラクティブモードでコンテナに入り、
.ssh
$ docker-compose build
$ docker-compose up -d
$ docker-compose exec app bash
> ls -la ~/.ssh
#秘密鍵が無いことを確認
#Cntl+Dかexitでインタラクティブモードを抜ける
ここから起動しているコンテナへ秘密鍵を付与します。
DockerでホストOSから起動中のコンテナにコピーする場合、
docker cp
docker-cpの用法としては、
$ docker cp [ホストから送りたいファイル] [送り先のコンテナ名]:[コンテナ内の送信先ディレクトリ]
というように利用します。
docker-compose.ymlでコンテナ名を付けている場合(
container_name: my-app-dev
#👇秘密鍵をコンテナへ転送する
$ docker cp ~/.ssh/id_ed25519 my-app-dev:/usr/src/app/.ssh/
とすることで先ほどのDockerfileでCOPYした場合と同じことになります。
もしもdocker-compose.ymlでコンテナ名を付けていない場合には、
docker-compose ps
-q
$ docker cp ~/.ssh/id_ed25519 $(docker-compose ps -q app):/usr/src/app/.ssh/
ではコンテナへ再度インタラクティブモードに入って秘密鍵がコピーされているか確認してみます。
$ docker-compose exec app bash
bash-5.1# ls -la .ssh/
-rw------- 1 1000 1000 399 Feb 15 2021 id_ed25519
このように今度は直接ホスト側の任意のディレクトリからコンテナ側に直接鍵を注入できています。
この方法とわざわざ作業ディレクトリにキーをコピーして更新するような必要もないですので、先程よりも少しだけ楽です。
ポイントだけ掻い摘むと、DockerfileへCOPYで埋め込むよりもコンテナを立ち上げる前に一手間かかりますが、以下のコマンドでGitHubレポジトリの操作が可能な開発環境コンテナに仕上がると思います。
最終的に、
$ docker-compose up -d && \
docker cp ~/.ssh/id_ed25519 my-app-dev:/usr/src/app/.ssh/ && \
docker-compose exec app bash
と、SSH秘密キーを分離しながら運用するのが、もっとも安全なやり方と言えます。
余談〜Expectコマンドで毎回コンテナの立ち上げでGitHubにログインするのを自動化する
先程の
特に、秘密鍵でGitHubに初回接続する際には、
ssh -T git@github.com
yes
そこで、この対話的な手続きを自動化するのが
Expectコマンド
Alpine Linuxではパッケージインストールして利用できるようになります。
FROM alpine:3.18
RUN apk update && apk upgrade && \
apk add --no-cache bash git openssh
#👇Expectを追加
RUN apk add --no-cache expect
CMD ["bash"]
Expectコマンドを含め、出来ればここらへんの一連の操作まとめて、以下の
container_start.sh
#!/bin/bash
docker-compose up -d
docker cp ~/.ssh/id_ed25519 my-app-dev:/usr/src/app/.ssh/
docker-compose exec app bash -c '
eval "$(ssh-agent)"
ssh-add .ssh/id_ed25519
expect -c "
spawn ssh -T git@github.com
expect \"Are you sure you want to continue\" { send yes }
"
bash
'
では最後にこのスクリプトでGitHubのログインまで一括で完了するか確かめてみましょう。
$ chmod +x container_start.sh
$ ./container_start.sh
Agent pid 88
Identity added: .ssh/id_ed25519 (tacoskingdom)
Hi *******! You've successfully authenticated, but GitHub does not provide shell access.
bash-5.1#
ということでここまでGitHubアクセス認証済みのセキュアな開発用Dockerコンテナを作成するためのやり方を考察してみました。
SSH秘密キーを更新する
キーが有効期限を過ぎてしまうと、
$ git ...
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: POSSIBLE DNS SPOOFING DETECTED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
The RSA host key for github.com has changed,
and the key for the corresponding IP address ***.***.***.***
is unknown. This could either mean that
DNS SPOOFING is happening or the IP address for the host
and its host key have changed at the same time.
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
@ WARNING: REMOTE HOST IDENTIFICATION HAS CHANGED! @
@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@
IT IS POSSIBLE THAT SOMEONE IS DOING SOMETHING NASTY!
Someone could be eavesdropping on you right now (man-in-the-middle attack)!
It is also possible that a host key has just been changed.
The fingerprint for the RSA key sent by the remote host is
SHA256:xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.
Please contact your system administrator.
Add correct host key in /home/xxxxxx/.ssh/known_hosts to get rid of this message.
Offending RSA key in /home/xxxxxx/.ssh/known_hosts:x
remove with:
ssh-keygen -f "/home/xxxxxx/.ssh/known_hosts" -R "github.com"
RSA host key for github.com has changed and you have requested strict checking.
Host key verification failed.
fatal: Could not read from remote repository.
Please make sure you have the correct access rights
and the repository exists.
のような警告が表示されるようになります。
一旦、GitHubのダッシュボードに移り、操作がコケてしまったプロジェクトの状態を確認してみましょう。

[Clone] > [SSH]
この場合は、新しくレポジトリ管理者が新しいSSHキーを作り直さないといけないようです。
そのまま
[add a new public key]

GitHubに公開キーを設定したら、ローカルにあるSSHクライアント側にはペアの秘密キーを設定し直したら、無事いつものgitコマンドが使えるようになります。
まとめ
今回はGitHubレポジトリにed25519方式のSSH接続を試す方法をやってみました。
普段GitHubを使う分にはhttpsからのトークン認証(GitHub公式ではこちらを推奨)からの操作のほうが楽ではあるのですが、カンパニーアカウントなどのより堅牢な運用が求められる場合には、SSH接続の利用は検討に値すると思います。
参考サイト
記事を書いた人
ナンデモ系エンジニア
主にAngularでフロントエンド開発することが多いです。 開発環境はLinuxメインで進めているので、シェルコマンドも多用しております。 コツコツとプログラミングするのが好きな人間です。
カテゴリー