Skip to content

Commit

Permalink
Set credsStore to wincred.exe unless it already points to a working h…
Browse files Browse the repository at this point in the history
…elper.

Signed-off-by: Jan Dubois <[email protected]>
  • Loading branch information
jandubois committed Jan 29, 2025
1 parent b777df0 commit 92de96c
Show file tree
Hide file tree
Showing 3 changed files with 40 additions and 14 deletions.
4 changes: 2 additions & 2 deletions src/go/wsl-helper/cmd/wsl_integration_docker_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (

var wslIntegrationDockerViper = viper.New()

// wslIntegrationDockerCmd represents the `wsl integration docker-plugin` command
// wslIntegrationDockerCmd represents the `wsl integration docker` command
var wslIntegrationDockerCmd = &cobra.Command{
Use: "docker",
Short: "Commands for managing docker config for WSL integration",
Expand All @@ -43,7 +43,7 @@ var wslIntegrationDockerCmd = &cobra.Command{
return fmt.Errorf("failed to locate home directory: %w", err)
}

if err := integration.SetupPluginDirConfig(homeDir, pluginDir, state); err != nil {
if err := integration.UpdateDockerConfig(homeDir, pluginDir, state); err != nil {
return err
}

Expand Down
30 changes: 27 additions & 3 deletions src/go/wsl-helper/pkg/integration/docker_linux.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"errors"
"fmt"
"os"
"os/exec"
"path"
"path/filepath"
"slices"
Expand All @@ -30,11 +31,14 @@ import (

const (
pluginDirsKey = "cliPluginsExtraDirs"
credsStoreKey = "credsStore"

dockerCredentialWinCredExe = "wincred.exe"
)

// SetupPluginDirConfig configures docker CLI to load plugins from the directory
// given.
func SetupPluginDirConfig(homeDir, pluginPath string, enabled bool) error {
// UpdateDockerConfig configures docker CLI to load plugins from the directory
// given. It also sets the credential helper to wincred.exe.
func UpdateDockerConfig(homeDir, pluginPath string, enabled bool) error {
configPath := filepath.Join(homeDir, ".docker", "config.json")
config := make(map[string]any)

Expand All @@ -52,6 +56,16 @@ func SetupPluginDirConfig(homeDir, pluginPath string, enabled bool) error {
}
}

replaceCredsStore := true
if credsStoreRaw, ok := config[credsStoreKey]; ok {
if credsStore, ok := credsStoreRaw.(string); ok {
replaceCredsStore = !isCredHelperWorking(credsStore)
}
}
if replaceCredsStore {
config[credsStoreKey] = dockerCredentialWinCredExe
}

var dirs []string

if dirsRaw, ok := config[pluginDirsKey]; ok {
Expand Down Expand Up @@ -109,6 +123,16 @@ func SetupPluginDirConfig(homeDir, pluginPath string, enabled bool) error {
return nil
}

// isCredHelperWorking verifies that the credential helper can be called, and doesn't need to be replaced.
func isCredHelperWorking(credsStore string) bool {
// The proprietary "desktop" helper is always replaced with the default helper.
if credsStore == "" || credsStore == "desktop" || credsStore == "desktop.exe" {
return false
}
credHelper := fmt.Sprintf("docker-credential-%s", credsStore)
return exec.Command(credHelper, "list").Run() == nil
}

// RemoveObsoletePluginSymlinks removes symlinks in the docker CLI plugin
// directory which are children of the given directory.
func RemoveObsoletePluginSymlinks(homeDir, binPath string) error {
Expand Down
20 changes: 11 additions & 9 deletions src/go/wsl-helper/pkg/integration/docker_linux_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,13 +29,13 @@ import (
"github.com/rancher-sandbox/rancher-desktop/src/go/wsl-helper/pkg/integration"
)

func TestSetupPluginDirConfig(t *testing.T) {
func TestUpdateDockerConfig(t *testing.T) {
t.Parallel()
t.Run("create config file", func(t *testing.T) {
homeDir := t.TempDir()
pluginPath := t.TempDir()

assert.NoError(t, integration.SetupPluginDirConfig(homeDir, pluginPath, true))
assert.NoError(t, integration.UpdateDockerConfig(homeDir, pluginPath, true))

bytes, err := os.ReadFile(path.Join(homeDir, ".docker", "config.json"))
require.NoError(t, err, "error reading docker CLI config")
Expand All @@ -45,6 +45,8 @@ func TestSetupPluginDirConfig(t *testing.T) {
value := config["cliPluginsExtraDirs"]
require.Contains(t, config, "cliPluginsExtraDirs")
require.Contains(t, value, pluginPath, "did not contain plugin path")
credStore := config["credsStore"]
require.Equal(t, credStore, "wincred.exe")
})
t.Run("update config file", func(t *testing.T) {
homeDir := t.TempDir()
Expand All @@ -54,15 +56,15 @@ func TestSetupPluginDirConfig(t *testing.T) {
existingContents := []byte(`{"credsStore": "nothing"}`)
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))

require.NoError(t, integration.SetupPluginDirConfig(homeDir, pluginPath, true))
require.NoError(t, integration.UpdateDockerConfig(homeDir, pluginPath, true))

bytes, err := os.ReadFile(path.Join(homeDir, ".docker", "config.json"))
require.NoError(t, err, "error reading docker CLI config")
var config map[string]any
require.NoError(t, json.Unmarshal(bytes, &config))

assert.Subset(t, config, map[string]any{"credsStore": "nothing"})
assert.Subset(t, config, map[string]any{"cliPluginsExtraDirs": []any{pluginPath}})
assert.Subset(t, config, map[string]any{"credsStore": "wincred.exe"})
})
t.Run("do not add multiple instances", func(t *testing.T) {
homeDir := t.TempDir()
Expand All @@ -77,7 +79,7 @@ func TestSetupPluginDirConfig(t *testing.T) {
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))
config = make(map[string]any)

require.NoError(t, integration.SetupPluginDirConfig(homeDir, pluginPath, true))
require.NoError(t, integration.UpdateDockerConfig(homeDir, pluginPath, true))

bytes, err := os.ReadFile(configPath)
require.NoError(t, err, "error reading docker CLI config")
Expand All @@ -97,7 +99,7 @@ func TestSetupPluginDirConfig(t *testing.T) {
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))
config = make(map[string]any)

require.NoError(t, integration.SetupPluginDirConfig(homeDir, pluginPath, false))
require.NoError(t, integration.UpdateDockerConfig(homeDir, pluginPath, false))

bytes, err := os.ReadFile(configPath)
require.NoError(t, err, "error reading docker CLI config")
Expand All @@ -115,7 +117,7 @@ func TestSetupPluginDirConfig(t *testing.T) {
existingContents := []byte(`this is not JSON`)
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))

assert.Error(t, integration.SetupPluginDirConfig(homeDir, pluginPath, true))
assert.Error(t, integration.UpdateDockerConfig(homeDir, pluginPath, true))

bytes, err := os.ReadFile(configPath)
require.NoError(t, err, "error reading docker CLI config")
Expand All @@ -132,7 +134,7 @@ func TestSetupPluginDirConfig(t *testing.T) {
require.NoError(t, err)
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))

require.Error(t, integration.SetupPluginDirConfig(homeDir, pluginPath, false))
require.Error(t, integration.UpdateDockerConfig(homeDir, pluginPath, false))

bytes, err := os.ReadFile(configPath)
require.NoError(t, err, "error reading docker CLI config")
Expand All @@ -152,7 +154,7 @@ func TestSetupPluginDirConfig(t *testing.T) {
require.NoError(t, err)
require.NoError(t, os.WriteFile(configPath, existingContents, 0o644))

require.Error(t, integration.SetupPluginDirConfig(homeDir, pluginPath, false))
require.Error(t, integration.UpdateDockerConfig(homeDir, pluginPath, false))

bytes, err := os.ReadFile(configPath)
require.NoError(t, err, "error reading docker CLI config")
Expand Down

0 comments on commit 92de96c

Please sign in to comment.