From 29fa49fa5f761f63afae5ce86b8bc409c318f459 Mon Sep 17 00:00:00 2001 From: AlbertSun Date: Wed, 10 Jun 2026 20:18:33 +0800 Subject: [PATCH] opt(proxy): add config & auth test coverage --- cmd/config/config_test.go | 122 ++++++++++++++++++++++++++++ cmd/config/init_auth_method_test.go | 29 +++++++ 2 files changed, 151 insertions(+) diff --git a/cmd/config/config_test.go b/cmd/config/config_test.go index bf2a9bcb8..9924f756b 100644 --- a/cmd/config/config_test.go +++ b/cmd/config/config_test.go @@ -205,6 +205,88 @@ func TestSaveInitConfig_OmitLangPreservesPrior(t *testing.T) { } } +func TestKeyRefFromResult_PrivateKeyJWT(t *testing.T) { + ref := keyRefFromResult(&configInitResult{ + AuthMethod: core.AuthMethodPrivateKeyJWT, + KeyLabel: "lark-cli-default", + }) + if ref == nil { + t.Fatal("keyRefFromResult returned nil") + } + if ref.Source != "tee" || ref.ID != "lark-cli-default" { + t.Fatalf("key ref = %#v, want tee/lark-cli-default", ref) + } + + if ref := keyRefFromResult(&configInitResult{AuthMethod: core.AuthMethodPrivateKeyJWT}); ref != nil { + t.Fatalf("missing key label should not persist key ref, got %#v", ref) + } + if ref := keyRefFromResult(&configInitResult{AuthMethod: core.AuthMethodClientSecret, KeyLabel: "ignored"}); ref != nil { + t.Fatalf("client_secret should not persist key ref, got %#v", ref) + } + if ref := keyRefFromResult(nil); ref != nil { + t.Fatalf("nil result should not persist key ref, got %#v", ref) + } +} + +func TestSaveInitConfig_PrivateKeyJWTSingleAppPersistsSecretlessAuth(t *testing.T) { + t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) + f, _, _, _ := cmdutil.TestFactory(t, nil) + + keyRef := &core.SecretRef{Source: "tee", ID: "lark-cli-default"} + if err := saveInitConfig("", nil, f, "cli_pkjwt", core.SecretInput{}, core.BrandFeishu, "en_us", core.AuthMethodPrivateKeyJWT, keyRef); err != nil { + t.Fatalf("saveInitConfig private_key_jwt single app: %v", err) + } + + got, err := core.LoadMultiAppConfig() + if err != nil { + t.Fatalf("LoadMultiAppConfig: %v", err) + } + if len(got.Apps) != 1 { + t.Fatalf("apps len = %d, want 1", len(got.Apps)) + } + app := got.Apps[0] + if app.AppId != "cli_pkjwt" { + t.Fatalf("AppId = %q, want cli_pkjwt", app.AppId) + } + if app.AuthMethod != core.AuthMethodPrivateKeyJWT { + t.Fatalf("AuthMethod = %q, want private_key_jwt", app.AuthMethod) + } + if app.KeyRef == nil || app.KeyRef.Source != "tee" || app.KeyRef.ID != "lark-cli-default" { + t.Fatalf("KeyRef = %#v, want tee/lark-cli-default", app.KeyRef) + } + if app.AppSecret.Ref != nil || app.AppSecret.Plain != "" { + t.Fatalf("private_key_jwt config must stay secretless, AppSecret=%#v", app.AppSecret) + } +} + +func TestSaveInitConfig_PrivateKeyJWTProfilePersistsSecretlessAuth(t *testing.T) { + t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) + f, _, _, _ := cmdutil.TestFactory(t, nil) + + keyRef := &core.SecretRef{Source: "tee", ID: "lark-cli-default"} + if err := saveInitConfig("prod", &core.MultiAppConfig{}, f, "cli_pkjwt", core.SecretInput{}, core.BrandLark, "en_us", core.AuthMethodPrivateKeyJWT, keyRef); err != nil { + t.Fatalf("saveInitConfig private_key_jwt profile: %v", err) + } + + got, err := core.LoadMultiAppConfig() + if err != nil { + t.Fatalf("LoadMultiAppConfig: %v", err) + } + app := got.FindApp("prod") + if app == nil { + t.Fatalf("profile prod not saved: %#v", got.Apps) + } + if app.AuthMethod != core.AuthMethodPrivateKeyJWT { + t.Fatalf("AuthMethod = %q, want private_key_jwt", app.AuthMethod) + } + if app.KeyRef == nil || app.KeyRef.Source != "tee" || app.KeyRef.ID != "lark-cli-default" { + t.Fatalf("KeyRef = %#v, want tee/lark-cli-default", app.KeyRef) + } + if app.AppSecret.Ref != nil || app.AppSecret.Plain != "" { + t.Fatalf("private_key_jwt profile must stay secretless, AppSecret=%#v", app.AppSecret) + } +} + // TestConfigInitCmd_InvalidLang verifies a non-empty --lang on config init is // strictly validated the same way bind validates: wrong-case / typo / removed // codes / hyphen form all exit with ExitValidation. (Empty is a no-op.) @@ -390,6 +472,46 @@ func TestSaveAsProfile_RejectsProfileNameCollisionWithExistingAppID(t *testing.T } } +func TestSaveAsProfile_UpdatePersistsPrivateKeyJWT(t *testing.T) { + t.Setenv("LARKSUITE_CLI_CONFIG_DIR", t.TempDir()) + + existing := &core.MultiAppConfig{ + Apps: []core.AppConfig{{ + Name: "prod", + AppId: "cli_prod", + AppSecret: core.PlainSecret("old-secret"), + Brand: core.BrandFeishu, + Users: []core.AppUser{{UserOpenId: "ou_1", UserName: "User"}}, + }}, + } + keyRef := &core.SecretRef{Source: "tee", ID: "lark-cli-default"} + + if err := saveAsProfile(existing, keychain.KeychainAccess(&noopConfigKeychain{}), "prod", "cli_prod", core.SecretInput{}, core.BrandLark, "en_us", core.AuthMethodPrivateKeyJWT, keyRef); err != nil { + t.Fatalf("saveAsProfile update private_key_jwt: %v", err) + } + + got, err := core.LoadMultiAppConfig() + if err != nil { + t.Fatalf("LoadMultiAppConfig: %v", err) + } + app := got.FindApp("prod") + if app == nil { + t.Fatalf("profile prod not saved: %#v", got.Apps) + } + if app.AuthMethod != core.AuthMethodPrivateKeyJWT { + t.Fatalf("AuthMethod = %q, want private_key_jwt", app.AuthMethod) + } + if app.KeyRef == nil || app.KeyRef.Source != "tee" || app.KeyRef.ID != "lark-cli-default" { + t.Fatalf("KeyRef = %#v, want tee/lark-cli-default", app.KeyRef) + } + if app.AppSecret.Ref != nil || app.AppSecret.Plain != "" { + t.Fatalf("private_key_jwt update must stay secretless, AppSecret=%#v", app.AppSecret) + } + if len(app.Users) != 1 || app.Users[0].UserOpenId != "ou_1" { + t.Fatalf("same-app update should preserve users, Users=%#v", app.Users) + } +} + func TestUpdateExistingProfileWithoutSecret_RejectsAppIDChange(t *testing.T) { multi := &core.MultiAppConfig{ CurrentApp: "prod", diff --git a/cmd/config/init_auth_method_test.go b/cmd/config/init_auth_method_test.go index a109f4259..4d5e2ea95 100644 --- a/cmd/config/init_auth_method_test.go +++ b/cmd/config/init_auth_method_test.go @@ -4,12 +4,29 @@ package config import ( + "context" + "crypto" "testing" + "github.com/larksuite/cli/extension/keysigner" "github.com/larksuite/cli/internal/cmdutil" "github.com/larksuite/cli/internal/core" ) +type authMethodTestSigner struct{} + +func (authMethodTestSigner) EnsureKey(context.Context, keysigner.KeyRef) (crypto.PublicKey, error) { + return nil, nil +} + +func (authMethodTestSigner) PublicKey(context.Context, keysigner.KeyRef) (crypto.PublicKey, error) { + return nil, nil +} + +func (authMethodTestSigner) Sign(context.Context, keysigner.KeyRef, []byte) ([]byte, string, error) { + return nil, "", nil +} + // TestResolveRegisterAuthMethod covers the non-interactive gating paths. No TEE // signer is registered in this test binary, so private_key_jwt must be rejected. func TestResolveRegisterAuthMethod(t *testing.T) { @@ -19,6 +36,10 @@ func TestResolveRegisterAuthMethod(t *testing.T) { t.Errorf("client_secret: got (%q, %v), want (client_secret, nil)", m, err) } + if m, err := resolveRegisterAuthMethod(f, ""); err != nil || m != core.AuthMethodClientSecret { + t.Errorf("default: got (%q, %v), want (client_secret, nil)", m, err) + } + if _, err := resolveRegisterAuthMethod(f, "bogus"); err == nil { t.Error("bogus auth-method: expected error") } @@ -26,6 +47,14 @@ func TestResolveRegisterAuthMethod(t *testing.T) { if _, err := resolveRegisterAuthMethod(f, core.AuthMethodPrivateKeyJWT); err == nil { t.Error("private_key_jwt without a signer: expected error") } + + prevSigner := keysigner.Active() + keysigner.Register(authMethodTestSigner{}) + t.Cleanup(func() { keysigner.Register(prevSigner) }) + + if m, err := resolveRegisterAuthMethod(f, core.AuthMethodPrivateKeyJWT); err != nil || m != core.AuthMethodPrivateKeyJWT { + t.Errorf("private_key_jwt with signer: got (%q, %v), want (private_key_jwt, nil)", m, err) + } } // TestResolveFinalAuthMethod locks the authoritative-method logic. The 2nd case