GitHub 即日起支援使用 Security Key 進行 Git 操作

GitHub 開始支援使用 security key 進行 Git 操作啦!

這應該是各家科技巨頭當中,第一個支援 security key 進行 SSH login 的服務吧。 筆者昨天 5/10 才在公司內分享如何使用 security key 來做 SSH login, 沒想到 Yubico 和 GitHub 也剛好在昨天一起同步更新 blog 文章,通知大家這個新功能。 喜極而泣..

以下簡單介紹如何使用這個新功能。 為了方便解說及避免誤會,後述內容均以正式名稱 authenticator 代稱 security key。

如何使用

首先當然要有一把 authenticator,如果還沒有,趕快去買一把囉。 :D

第一步,在 authenticator 內產生新的 key pair。

產生 key pair 的流程和傳統放在檔案系統上的差不多,只是 key type 要指定代表 authenticator 的 type。

1
ssh-keygen -t ecdsa-sk

產生的過程,根據不同的 authenticator,會有要求按一下 且/或 輸入 PIN code 驗證身分。 此步驟會在 authenticator 內產生一組 key pair,並將 public key 寫到檔案系統上。 平常放 private key 的那個檔案還是會產生,不過這次裡面放的會是一個 key handle。

第二步,透過 GitHub 的 web UI 上傳 public key

上傳完之後,沒意外就可以順利使用了,可以試著 clone 一些 project

1
2
3
4
$ git clone git@github.com:github/secure_headers.git
Cloning into 'secure_headers'...
Confirm user presence for key ECDSA-SK SHA256:........
User presence confirmed

若確認 OK,之後的 Git 操作都可以透過隨身攜帶的 authenticator 保護, 只要按一下 authenticator 即可。

設定完之後,若沒有拿出 authenticator,就不能進行 push / pull 操作。 只要確保 authenticator 還在身上,就可以安心睡大覺。 (再也不用擔心 private key 放在公司電腦上會被摸走了!)

進階使用方式

FIDO 2 authenticator 博大精深,除了上述的基本使用流程外,還有些細節可以設定。

以下分別介紹三個進階使用技巧:

要求身分驗證 (User Verification) 才能使用 Authenticator

根據每個人平常保管鑰匙習慣的差異,可能有人會擔心 authenticator 真的被摸走。

但 authenticator 也有支援一定要驗甚身分 (e.g. PIN code or 指紋辨識) 後才能 使用內部的 key pair 的功能。

要如何使用呢? 只要在產生 key pair 的過程中多下一個 flag 即可。

1
ssh-keygen -t ecdsa-sk -O verify-required

若之後要使用由此方式產生的 key pair,除了手指按一下 authenticator 之外,還會要求 使用者輸入 PIN code 才能順利完成操作。如此即使 authenticator 被偷走了,也不用太緊張。

全自動使用 Authenticator (避免 User Presence Check)

若把 authenticator 插上電腦後,想要隨時隨地都進行 push / pull, 但不要每次都手按一下 authenticator。這種自動化的使用情境 OpenSSH 其實也是有支援的。

使用的方式也是在產生 key pair 時多帶一個參數。

1
ssh-keygen -t ecdsa-sk -O no-touch-required

同時在將 public key 部屬到目標機器上時,在 public key 該行前面多下 no-touch-required 即可。 (詳情請見 ssh-keygen(1)sshd(8))

以此方始產生的 key pair 在使用時就不需要每次都手按一下,可以全自動使用。

不過,雖然 OpenSSH 有支援此種使用情境,但目前 GitHub 禁止這種使用方式

節錄自上述 blog 文章

While we understand the appeal of removing the need for the taps, we determined our current approach to require presence and intention is the best balance between usability and security.

所以在 GitHub 上,若想要全自動操作,只能回去用一般的 SSH key 或 API token 囉。

避免手動複製 Key Handle

前面有提到,原先檔案系統上用來放 private key 的檔案會變成拿來擺放 key handle。

這意味著,當我們想在新的機器上透過 SSH 進行 Git 操作時,除了拿出 authenticator 之外, 也需要把原先的 key handle 檔案複製到新的機器上。 且若 key handle 檔案掉了,該組 key pair 就不能使用了。

若要避免此問題,就要用上 authenticator 的另一個進階功能 discoverable credentials / resident keys 。

1
ssh-keygen -t ecdsa-sk -O resident

使用此類型的 key pair 時,會在 authenticator 上消耗一些儲存空間。但換來的好處是, 使用者可以在新的機器上,把 key handle 從 authenticator 內抽出來。

1
ssh-keygen -K # extract discoverable credentials

如此就不用手動複製擺放 key handle 的 private key 檔案了。

但要注意的是此類型 key pair 會消耗 authenticator 的空間。 每把 authenticator 可以放多少 key pair 要再自行查閱官方文件。

結語

以上介紹了基本使用情境及三種可能的進階使用方式。

筆者在 2014 年第一次注意到 FIDO (U2F) 標準,當時就在想像沒有密碼的世界。 如今,藉由 FIDO 2 security key 的普及,當初所想的美好願景似乎在慢慢地實現中..

希望未來能看到 security key 運用在更多場景上!

在 macOS 上架設 Apache 與 PHP-FPM

工作上因為一些特殊需求,需要在 macOS 環境下架設 Apache + PHP-FPM 的使用環境。好在 macOS 本來就有預裝 Apache 以及 PHP-FPM,並提供 Apache 的 launchd 設定檔,要在 macOS 上架設這個服務並不困難。

本文介紹如何以最低限度的設定,在 macOS 上跑 Apache + PHP-FPM。以筆記的方式呈現,不會有太多的講解。

Notes

  • 筆者是在 macOS 10.14 與 10.15 上測試此流程
  • macOS 系統上,/etc 是一個 symblic link 連至 /private/etc/var, /tmp 也有相同行為。

設定與啟用 PHP-FPM

複製並修改 PHP-FPM 設定檔

系統內有會自帶 PHP-FPM 的 default 設定檔,將其複製一份出來,並修改內容。

1
2
$ sudo cp /etc/php-fpm.conf.default /etc/php-fpm.conf
$ sudo cp /etc/php-fpm.d/www.conf.default /etc/php-fpm.d/www.conf

將執行身分從 nobody 修改為 _www (與 Apache httpd一致)。

1
$ sudo vim /etc/php-fpm.d/www.conf
1
2
3
4
5
; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
; will be used.
user = _www
group = _www

修改 error_log,調整 log file 的路徑。

1
$ sudo vim /etc/php-fpm.conf
1
2
3
4
5
6
; Error log file
; If it's set to "syslog", log is sent to syslogd instead of being written
; into a local file.
; Note: the default prefix is /usr/var
; Default Value: log/php-fpm.log
error_log = /var/log/php-fpm.log

新增 PHP-FPM 的 launchd 設定檔並啟用

創一個 launchd daemon 設定檔給 PHP-FPM 使用, 此舉目的為讓 PHP-FPM daemon 可以在 macOS 開機時自己啟用。

建議將設定檔放在 /Library/LaunchDaemons 下,參照 launchd 的文件, 此位置是供第三方軟體擺放 daemon 設定使用。

1
$ sudo vim /Library/LaunchDaemons/com.example.php-fpm.plist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Disabled</key>
<true/>
<key>Label</key>
<string>com.example.php-fpm</string>
<key>ProgramArguments</key>
<array>
<string>/usr/sbin/php-fpm</string>
<string>--nodaemonize</string>
</array>
<key>OnDemand</key>
<false/>
</dict>
</plist>

做好設定檔之後,用 launchctl 指令 load 此設定檔,並下參數告訴 macOS 之後此 daemon 要在開機時預設啟用。

1
$ sudo launchctl load -w /Library/LaunchDaemons/com.example.php-fpm.plist

上述指令執行完後, launchd 會把 PHP-FPM daemon 叫起。

1
2
3
4
$ ps aux | grep php
_www 515 0.0 0.0 4297608 648 ?? S 6:18PM 0:00.00 /usr/sbin/php-fpm
_www 514 0.0 0.0 4305800 628 ?? S 6:18PM 0:00.00 /usr/sbin/php-fpm
root 513 0.0 0.0 4305800 784 ?? Ss 6:18PM 0:00.00 /usr/sbin/php-fpm

設定並啟用 Apache Web Server

修改設定檔,讓 Apache 使用 proxy_moduleproxy_fcgi_module, 並確認 php7_module 沒被啟用。

需要本文的讀者應該不至於把 Apache PHP module 與 PHP-FPM 搞混.. XD

1
$ sudo vim /etc/apache2/httpd.conf
1
2
3
LoadModule proxy_module libexec/apache2/mod_proxy.so
LoadModule proxy_fcgi_module libexec/apache2/mod_proxy_fcgi.so
# LoadModule php7_module libexec/apache2/libphp7.so

<Directory "/Library/WebServer/Documents"> 或其他需要的地方內, 加入 PHP 的 handler,指向 PHP-FPM 預設提供服務的 socket。

1
2
3
4
5
6
7
<Directory "/Library/WebServer/Documents">
... 上略
<FilesMatch \.php$>
SetHandler "proxy:fcgi://localhost:9000/"
</FilesMatch>
</Directory>

Apache 的 daemon config 本來就存在於系統目錄內,但 Disable 的值被設為 true, 用下述 command 將 Apache daemon load 進 launchd 內,並讓 launchd 記錄此 daemon 應被啟用。

1
sudo launchctl load -w /System/Library/LaunchDaemons/org.apache.httpd.plist

與 PHP-FPM 相同,此指令下去之後,launchd 就會把 Apache 拉起。

此時可去 http://localhost/ 確認,如果看到大大的標題寫著

It works!

即代表 Apache 有順利執行。

確認 PHP-FPM 運作正常

丟一個 phpinfo 到 web server 的預設根目錄下。

1
$ sudo vim /Library/WebServer/Documents/phpinfo.php
1
2
3
<?php
phpinfo();
?>

之後連上 http://localhost/phpinfo.php ,看到 Server APIFPM/FastCGI 即可。 :D