feat(vault-tui): implement KV client and service for managing secrets
- 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.
This commit is contained in:
@@ -0,0 +1,107 @@
|
||||
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, "'", "''") + "'"
|
||||
}
|
||||
Reference in New Issue
Block a user