- Added internal/vault/client.go for creating a Vault client with configuration settings. - Introduced internal/vault/errors.go to classify Vault API errors for better UI handling. - Created internal/vault/kv.go to manage KV secrets, including listing, reading, writing, and deleting operations. - Implemented internal/vault/mounts.go to list and describe secret engine mounts. - Developed internal/vault/service.go to provide a unified entry point for Vault operations. - Added internal/vault/kv_test.go for comprehensive testing of KV operations. - Introduced internal/ui/toast.go for transient notifications in the UI. - Added renovate.json for dependency management and updates.
108 lines
3.4 KiB
Go
108 lines
3.4 KiB
Go
package oidc
|
|
|
|
import (
|
|
"fmt"
|
|
"os"
|
|
"os/exec"
|
|
"runtime"
|
|
"strings"
|
|
)
|
|
|
|
// openBrowser tries, in order: an explicit command override, $BROWSER, then
|
|
// platform-appropriate auto-detection. It exists instead of
|
|
// github.com/pkg/browser because that package shells out to xdg-open, which
|
|
// is absent on a bare WSL2 install (verified: no xdg-open, no
|
|
// xclip/wl-copy, no wslview on this project's own dev machine) — there,
|
|
// the working option is handing the URL to the Windows side via
|
|
// powershell.exe or cmd.exe.
|
|
//
|
|
// override, when non-empty, is treated as a command template: "%s" is
|
|
// replaced with the URL if present, otherwise the URL is appended as the
|
|
// final argument. It is run through the shell so users can supply
|
|
// something like `firefox --new-tab %s`.
|
|
func openBrowser(override, url string) error {
|
|
if override != "" {
|
|
return runShell(substituteOrAppend(override, url))
|
|
}
|
|
if b := os.Getenv("BROWSER"); b != "" {
|
|
return runShell(substituteOrAppend(b, url))
|
|
}
|
|
|
|
for _, cand := range candidates(url) {
|
|
cmd := exec.Command(cand[0], cand[1:]...)
|
|
if err := cmd.Start(); err == nil {
|
|
// Don't Wait(): a real browser backgrounds itself, and waiting on
|
|
// e.g. `cmd.exe /c start` (which returns immediately anyway) is
|
|
// harmless, but waiting on something that stays foregrounded
|
|
// would block the login flow.
|
|
return nil
|
|
}
|
|
}
|
|
return fmt.Errorf("no working browser launcher found for %s (tried: %s)", runtime.GOOS, candidateNames(url))
|
|
}
|
|
|
|
// candidates returns launcher argv lists to try in order, most-specific
|
|
// (and most likely to actually work on this host) first.
|
|
func candidates(url string) [][]string {
|
|
var out [][]string
|
|
if isWSL() {
|
|
out = append(out,
|
|
[]string{"wslview", url},
|
|
[]string{"powershell.exe", "-NoProfile", "-NonInteractive", "-Command", "Start-Process", quoteForPowerShell(url)},
|
|
[]string{"cmd.exe", "/c", "start", "", url},
|
|
)
|
|
}
|
|
switch runtime.GOOS {
|
|
case "darwin":
|
|
out = append(out, []string{"open", url})
|
|
case "windows":
|
|
out = append(out, []string{"cmd", "/c", "start", "", url},
|
|
[]string{"rundll32", "url.dll,FileProtocolHandler", url})
|
|
default:
|
|
out = append(out, []string{"xdg-open", url}, []string{"x-www-browser", url})
|
|
}
|
|
return out
|
|
}
|
|
|
|
func candidateNames(url string) string {
|
|
var names []string
|
|
for _, c := range candidates(url) {
|
|
names = append(names, c[0])
|
|
}
|
|
return strings.Join(names, ", ")
|
|
}
|
|
|
|
// isWSL detects WSL1/2 by checking /proc/version for the "microsoft"
|
|
// marker Microsoft's kernel build injects there — the standard, widely
|
|
// used detection technique since there's no dedicated syscall for it.
|
|
func isWSL() bool {
|
|
if runtime.GOOS != "linux" {
|
|
return false
|
|
}
|
|
b, err := os.ReadFile("/proc/version")
|
|
if err != nil {
|
|
return false
|
|
}
|
|
v := strings.ToLower(string(b))
|
|
return strings.Contains(v, "microsoft") || strings.Contains(v, "wsl")
|
|
}
|
|
|
|
func substituteOrAppend(template, url string) string {
|
|
if strings.Contains(template, "%s") {
|
|
return fmt.Sprintf(template, url)
|
|
}
|
|
return template + " " + url
|
|
}
|
|
|
|
func runShell(command string) error {
|
|
cmd := exec.Command("sh", "-c", command)
|
|
return cmd.Start()
|
|
}
|
|
|
|
// quoteForPowerShell wraps url in single quotes for use inside a
|
|
// -Command argument; OIDC auth URLs are server-generated and may contain
|
|
// characters PowerShell would otherwise interpret.
|
|
func quoteForPowerShell(url string) string {
|
|
return "'" + strings.ReplaceAll(url, "'", "''") + "'"
|
|
}
|