Skip to content

Commit 4ef1633

Browse files
committed
feat: adding docker-credential-finch compat with native cred socket
Signed-off-by: ayush-panta <[email protected]>
1 parent ef5d71d commit 4ef1633

File tree

1 file changed

+67
-1
lines changed

1 file changed

+67
-1
lines changed

cmd/finch-credential-helper/main.go

Lines changed: 67 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ import (
1313
"net"
1414
"net/http"
1515
"os"
16+
"path/filepath"
17+
"strings"
1618
"time"
1719

1820
dockertypes "github.com/docker/cli/cli/config/types"
@@ -24,6 +26,7 @@ import (
2426
const (
2527
// ConnectionTimeout is the timeout for connecting to the credential socket.
2628
ConnectionTimeout = 5 * time.Second
29+
BufferSize = 4096
2730
)
2831

2932
// CredentialSocketPath is the path to the credential socket.
@@ -51,6 +54,10 @@ func (h FinchCredentialHelper) List() (map[string]string, error) {
5154

5255
// Get retrieves credentials from the Finch daemon.
5356
func (h FinchCredentialHelper) Get(serverURL string) (string, string, error) {
57+
if os.Getenv("USE_NATIVE_CREDSTORE") != "" {
58+
return h.getFromCredSocket(serverURL)
59+
}
60+
5461
buildID := os.Getenv("FINCH_BUILD_ID")
5562
if buildID == "" {
5663
return "", "", credentials.NewErrCredentialsNotFound()
@@ -111,6 +118,65 @@ func (h FinchCredentialHelper) Get(serverURL string) (string, string, error) {
111118
return authConfig.Username, authConfig.Password, nil
112119
}
113120

121+
func (h FinchCredentialHelper) getFromCredSocket(serverURL string) (string, string, error) {
122+
credentialSocketPath := os.Getenv("FINCH_CREDENTIAL_SOCKET")
123+
if credentialSocketPath == "" {
124+
// detect WSL; Windows Finch uses direct fs mount instead of port forwarding
125+
if strings.Contains(os.Getenv("PATH"), "/mnt/c") || os.Getenv("WSL_DISTRO_NAME") != "" {
126+
finchDir := os.Getenv("FINCH_DIR")
127+
if finchDir != "" {
128+
credentialSocketPath = filepath.Join(finchDir, "lima", "data", "finch", "sock", "creds.sock")
129+
} else {
130+
return "", "", fmt.Errorf("FINCH_DIR environment variable not set; cannot find mounted socket")
131+
}
132+
} else {
133+
// reverse port forwarded sock from mac.yaml
134+
credentialSocketPath = "/run/finch-user-sockets/creds.sock"
135+
}
136+
}
137+
138+
// connect to socket
139+
conn, err := net.Dial("unix", credentialSocketPath)
140+
if err != nil {
141+
return "", "", credentials.NewErrCredentialsNotFound()
142+
}
143+
defer conn.Close()
144+
145+
// simple sanitize to fight injection
146+
serverURL = strings.ReplaceAll(serverURL, "\n", "")
147+
serverURL = strings.ReplaceAll(serverURL, "\r", "")
148+
149+
// send get command with URL through socket
150+
_, err = conn.Write([]byte("get\n" + serverURL + "\n"))
151+
if err != nil {
152+
return "", "", credentials.NewErrCredentialsNotFound()
153+
}
154+
155+
// read response
156+
response := make([]byte, BufferSize)
157+
n, err := conn.Read(response)
158+
if err != nil {
159+
return "", "", credentials.NewErrCredentialsNotFound()
160+
}
161+
162+
// parse response into credential struct (auth config breaking)
163+
var cred struct {
164+
ServerURL string `json:"ServerURL"`
165+
Username string `json:"Username"`
166+
Secret string `json:"Secret"`
167+
}
168+
if err := json.Unmarshal(response[:n], &cred); err != nil {
169+
return "", "", credentials.NewErrCredentialsNotFound()
170+
}
171+
172+
// Return empty credentials if no credentials found
173+
if cred.Username == "" && cred.Secret == "" {
174+
return "", "", credentials.NewErrCredentialsNotFound()
175+
}
176+
177+
return cred.Username, cred.Secret, nil
178+
}
179+
114180
func main() {
115181
credentials.Serve(FinchCredentialHelper{})
116-
}
182+
}

0 commit comments

Comments
 (0)