[インデックス 10364] exp/ssh クライアント機能テストの追加
コミット
- コミットハッシュ: 34466a14911163fadcc54725143b04c47d4080aa
- 作者: Dave Cheney dave@cheney.net
- 日付: 2011年11月13日 20:58:51 -0500
- コミットメッセージ: exp/ssh: add client functional tests
GitHub上でのコミットページへのリンク
https://github.com/golang/go/commit/34466a14911163fadcc54725143b04c47d4080aa
元コミット内容
exp/ssh: add client functional tests
Requires CL 5373055
R=rsc, agl, n13m3y3r
CC=golang-dev
https://golang.org/cl/5320053
このコミットは、Goの実験的SSH パッケージ(exp/ssh
)にクライアント機能テストを追加しました。61行のコードで新しいファイル client_func_test.go
を作成し、パスワード認証と公開鍵認証の両方をテストする機能を実装しました。
変更の背景
2011年当時、GoはSSHクライアント機能の実装を実験的パッケージ(exp/ssh
)として開発していました。このパッケージは、外部依存なしにGoアプリケーションからSSH接続を可能にする重要な機能でした。
Dave Cheneyは、2011年11月21日のブログ投稿で「Three new SSH client features in Go weekly.2011-11-18」として、以下の主要機能を発表しました:
- 公開鍵認証のサポート: クライアントが公開鍵認証をサポートするようになりました
- ClientKeyring インターフェース: 公開鍵認証を使用するためのインターフェースが追加されました
- 直接TCP/IP接続: SSH接続を介してTCP接続をトンネリングする実験的サポートが追加されました
これらの機能をテストするために、実際のSSHサーバーとの接続を試験する機能テストが必要となり、このコミットが作成されました。
前提知識の解説
SSH認証方式
SSH(Secure Shell)は、リモートシステムへの安全な接続を提供するネットワークプロトコルです。主要な認証方式には以下があります:
-
パスワード認証:
- 最も基本的な認証方式
- ユーザー名とパスワードを使用
- 比較的簡単だが、パスワードの漏洩リスクがある
-
公開鍵認証:
- 暗号化鍵ペア(公開鍵と秘密鍵)を使用
- より高いセキュリティレベルを提供
- 自動化されたパスワードレスログインが可能
- 攻撃者がサーバーに保存された公開鍵に対応する秘密鍵のコピーを必要とするため、ランダムな攻撃を防げる
Go の testing パッケージ
Go言語のtesting
パッケージは、自動テストのサポートを提供します。2011年当時から、Goのテストフレームワークは以下の特徴を持っていました:
- テスト関数は
Test
で始まり、_test.go
で終わるファイルに記述 flag
パッケージとの統合により、コマンドラインフラグを使用可能gotest
コマンド(後のgo test
)でテストを実行
機能テスト vs 単体テスト
- 単体テスト: 個別の関数や機能をテストするもの
- 機能テスト: 実際のサービスや外部システムと連携してテストするもの
このコミットで追加されたのは機能テストで、実際のSSHサーバーとの接続を必要とします。
技術的詳細
ファイル構成
新しく追加されたファイル:
src/pkg/exp/ssh/client_func_test.go
: 61行のテストファイル
実装の特徴
-
条件付きテスト実行:
- SSHサーバーが利用可能で、適切なフラグが設定されている場合のみテストが実行される
- フラグが設定されていない場合は、テストをスキップする
-
フラグベースの設定:
-ssh.user
: SSH ユーザー名-ssh.pass
: SSH パスワード-ssh.privkey
: SSH 秘密鍵ファイル
-
両方の認証方式のテスト:
- パスワード認証のテスト
- 公開鍵認証のテスト
-
リソース管理:
defer conn.Close()
で接続のクリーンアップを保証
コアとなるコードの変更箇所
ファイル: src/pkg/exp/ssh/client_func_test.go
// 新規ファイル作成(61行)
// ClientConn functional tests.
// These tests require a running ssh server listening on port 22
// on the local host. Functional tests will be skipped unless
// -ssh.user and -ssh.pass must be passed to gotest.
主要な変更点:
- パッケージ宣言:
package ssh
- フラグ定義:
sshuser
,sshpass
,sshprivkey
- テスト関数:
TestFuncPasswordAuth
,TestFuncPublickeyAuth
コアとなるコードの解説
フラグ定義部分
var (
sshuser = flag.String("ssh.user", "", "ssh username")
sshpass = flag.String("ssh.pass", "", "ssh password")
sshprivkey = flag.String("ssh.privkey", "", "ssh privkey file")
)
この部分では、コマンドラインフラグを定義しています。flag.String
関数は、以下の引数を受け取ります:
- フラグ名
- デフォルト値
- 説明文
パスワード認証テスト
func TestFuncPasswordAuth(t *testing.T) {
if *sshuser == "" {
t.Log("ssh.user not defined, skipping test")
return
}
config := &ClientConfig{
User: *sshuser,
Auth: []ClientAuth{
ClientAuthPassword(password(*sshpass)),
},
}
conn, err := Dial("tcp", "localhost:22", config)
if err != nil {
t.Fatalf("Unable to connect: %s", err)
}
defer conn.Close()
}
このテストでは:
sshuser
フラグが設定されているかチェック- パスワード認証用の
ClientConfig
を作成 localhost:22
への接続を試行- 接続に失敗した場合、テストを失敗させる
- 成功した場合、
defer
で接続をクローズ
公開鍵認証テスト
func TestFuncPublickeyAuth(t *testing.T) {
if *sshuser == "" {
t.Log("ssh.user not defined, skipping test")
return
}
kc := new(keychain)
if err := kc.loadPEM(*sshprivkey); err != nil {
t.Fatalf("unable to load private key: %s", err)
}
config := &ClientConfig{
User: *sshuser,
Auth: []ClientAuth{
ClientAuthPublickey(kc),
},
}
conn, err := Dial("tcp", "localhost:22", config)
if err != nil {
t.Fatalf("unable to connect: %s", err)
}
defer conn.Close()
}
このテストでは:
sshuser
フラグが設定されているかチェック- 新しい
keychain
オブジェクトを作成 - 秘密鍵ファイルを読み込み
- 公開鍵認証用の
ClientConfig
を作成 - 接続を試行し、結果を検証
設計上の重要な考慮事項
-
テストの条件付き実行: ユーザーが適切なフラグを設定していない場合、テストは静かにスキップされます。これにより、CI/CDパイプラインでテストが常に失敗することを防げます。
-
エラーハンドリング:
t.Fatalf
を使用してテストの失敗を明確に示し、詳細なエラーメッセージを提供します。 -
リソース管理:
defer
文を使用して、テスト完了後に接続が確実にクローズされるようにします。 -
実際のサービスへの依存: これらのテストは実際のSSHサーバーへの接続を必要とするため、統合テストの性質を持ちます。
関連リンク
- Go Code Review CL 5320053
- Go Code Review CL 5373055
- Dave Cheney's Blog: Three new SSH client features in Go weekly.2011-11-18
- Go testing package documentation
- Go flag package documentation
- golang.org/x/crypto/ssh current implementation