From 00c0b4d74a88fb693db8153a3de9d423a2f9809f Mon Sep 17 00:00:00 2001 From: hkfires <10558748+hkfires@users.noreply.github.com> Date: Mon, 29 Jun 2026 06:41:04 +0800 Subject: [PATCH] feat(auth): refactor authentication handling for plugins and add tests --- .../api/handlers/management/plugin_store.go | 32 +-------- internal/pluginstore/auth.go | 31 +++++++++ internal/pluginstore/auth_test.go | 67 +++++++++++++++++++ sdk/pluginstore/pluginstore.go | 4 ++ 4 files changed, 103 insertions(+), 31 deletions(-) diff --git a/internal/api/handlers/management/plugin_store.go b/internal/api/handlers/management/plugin_store.go index e9500cfa6..2643a8cbd 100644 --- a/internal/api/handlers/management/plugin_store.go +++ b/internal/api/handlers/management/plugin_store.go @@ -7,7 +7,6 @@ import ( "fmt" "io" "net/http" - "net/url" "runtime" "strings" "sync" @@ -637,36 +636,7 @@ func sanitizePluginStorePlatforms(platforms []pluginstore.Platform) []pluginStor } func pluginAuthConfigured(source pluginstore.Source, plugin pluginstore.Plugin, storeAuth []pluginstore.AuthConfig) bool { - if pluginstore.AuthConfigured(storeAuth, source.URL, pluginstore.RequestKindRegistry) { - return true - } - switch pluginstore.PluginInstallType(plugin) { - case pluginstore.InstallTypeDirect: - for _, artifact := range pluginstore.PluginArtifacts(plugin) { - if pluginstore.AuthConfigured(storeAuth, artifact.URL, pluginstore.RequestKindArtifact) { - return true - } - } - case pluginstore.InstallTypeGitHubRelease: - return pluginGitHubReleaseAuthConfigured(plugin, storeAuth) - } - return false -} - -func pluginGitHubReleaseAuthConfigured(plugin pluginstore.Plugin, storeAuth []pluginstore.AuthConfig) bool { - owner, repo, errRepository := pluginstore.GitHubRepositoryParts(plugin.Repository) - if errRepository != nil { - return false - } - releasesURL := fmt.Sprintf( - "https://api.github.com/repos/%s/%s/releases/", - url.PathEscape(owner), - url.PathEscape(repo), - ) - latestURL := releasesURL + "latest" - tagsURL := releasesURL + "tags/" - return pluginstore.AuthConfigured(storeAuth, latestURL, pluginstore.RequestKindMetadata) || - pluginstore.AuthConfigured(storeAuth, tagsURL, pluginstore.RequestKindMetadata) + return pluginstore.PluginAuthConfigured(source, plugin, storeAuth) } // latestPluginVersions resolves the latest release version of each registry diff --git a/internal/pluginstore/auth.go b/internal/pluginstore/auth.go index e50190e55..c72240287 100644 --- a/internal/pluginstore/auth.go +++ b/internal/pluginstore/auth.go @@ -96,6 +96,37 @@ func AuthConfigured(auth []AuthConfig, requestURL string, kind string) bool { } } +func PluginAuthConfigured(source Source, plugin Plugin, auth []AuthConfig) bool { + if AuthConfigured(auth, source.URL, RequestKindRegistry) { + return true + } + switch PluginInstallType(plugin) { + case InstallTypeDirect: + for _, artifact := range PluginArtifacts(plugin) { + if AuthConfigured(auth, artifact.URL, RequestKindArtifact) { + return true + } + } + case InstallTypeGitHubRelease: + return pluginGitHubReleaseAuthConfigured(plugin, auth) + } + return false +} + +func pluginGitHubReleaseAuthConfigured(plugin Plugin, auth []AuthConfig) bool { + owner, repo, errRepository := GitHubRepositoryParts(plugin.Repository) + if errRepository != nil { + return false + } + releasesURL := fmt.Sprintf( + "https://api.github.com/repos/%s/%s/releases/", + url.PathEscape(owner), + url.PathEscape(repo), + ) + return AuthConfigured(auth, releasesURL+"latest", RequestKindMetadata) || + AuthConfigured(auth, releasesURL+"tags/", RequestKindMetadata) +} + func applyPluginStoreAuth(headers http.Header, auth []AuthConfig, requestURL string, kind string) error { item, ok := matchingAuthConfig(auth, requestURL, kind) if !ok { diff --git a/internal/pluginstore/auth_test.go b/internal/pluginstore/auth_test.go index d2027c805..d672911ed 100644 --- a/internal/pluginstore/auth_test.go +++ b/internal/pluginstore/auth_test.go @@ -44,6 +44,73 @@ func TestPluginStoreAuthMatchesURLHostAndPathBoundaries(t *testing.T) { } } +func TestPluginAuthConfiguredCoversInstallRequestKinds(t *testing.T) { + t.Setenv("PLUGIN_STORE_TOKEN", "secret-token") + + source := Source{URL: "https://registry.example/registry.json"} + directPlugin := Plugin{ + ID: "sample-provider", + Version: "1.0.0", + Install: InstallPlan{ + Type: InstallTypeDirect, + Artifacts: []Artifact{{ + GOOS: "linux", + GOARCH: "amd64", + URL: "https://downloads.example/private/sample-provider.zip", + SHA256: "0123456789abcdef0123456789abcdef0123456789abcdef0123456789abcdef", + }}, + }, + } + gitHubPlugin := Plugin{ + ID: "sample-provider", + Repository: "https://github.com/author-name/sample-provider", + } + + tests := []struct { + name string + plugin Plugin + auth []AuthConfig + }{ + { + name: "registry", + plugin: gitHubPlugin, + auth: []AuthConfig{{ + Match: "https://registry.example/", + ApplyTo: []string{RequestKindRegistry}, + Type: AuthTypeBearer, + TokenEnv: "PLUGIN_STORE_TOKEN", + }}, + }, + { + name: "direct artifact", + plugin: directPlugin, + auth: []AuthConfig{{ + Match: "https://downloads.example/private/", + ApplyTo: []string{RequestKindArtifact}, + Type: AuthTypeBearer, + TokenEnv: "PLUGIN_STORE_TOKEN", + }}, + }, + { + name: "github metadata", + plugin: gitHubPlugin, + auth: []AuthConfig{{ + Match: "https://api.github.com/repos/author-name/sample-provider/releases/", + ApplyTo: []string{RequestKindMetadata}, + Type: AuthTypeBearer, + TokenEnv: "PLUGIN_STORE_TOKEN", + }}, + }, + } + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + if !PluginAuthConfigured(source, tt.plugin, tt.auth) { + t.Fatal("PluginAuthConfigured() = false, want true") + } + }) + } +} + func TestPluginStoreAuthHeaderIsReevaluatedAcrossRedirect(t *testing.T) { t.Setenv("PLUGIN_STORE_HEADER", "secret-token") diff --git a/sdk/pluginstore/pluginstore.go b/sdk/pluginstore/pluginstore.go index 73da2550a..74841bf59 100644 --- a/sdk/pluginstore/pluginstore.go +++ b/sdk/pluginstore/pluginstore.go @@ -106,6 +106,10 @@ func AuthConfigured(auth []AuthConfig, requestURL string, kind string) bool { return internalpluginstore.AuthConfigured(auth, requestURL, kind) } +func PluginAuthConfigured(source Source, plugin Plugin, auth []AuthConfig) bool { + return internalpluginstore.PluginAuthConfigured(source, plugin, auth) +} + func UpdateAvailable(installed, latest string) bool { return internalpluginstore.UpdateAvailable(installed, latest) }