Attempt to support unconfigured kerberos and weird Mac cred cache
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"path/filepath"
|
||||
"runtime"
|
||||
"strings"
|
||||
"syscall"
|
||||
"time"
|
||||
@@ -61,16 +62,31 @@ func credFetch(server, username string, noKerberos bool, logf func(string, ...an
|
||||
func credFetchKerberos(url string, logf func(string, ...any)) ([]byte, error) {
|
||||
krb5cfgPath := krb5ConfigPath()
|
||||
logf("Kerberos: loading config from %s", krb5cfgPath)
|
||||
krb5cfg, err := config.Load(krb5cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading krb5 config: %w", err)
|
||||
var krb5cfg *config.Config
|
||||
if _, statErr := os.Stat(krb5cfgPath); os.IsNotExist(statErr) && os.Getenv("KRB5_CONFIG") == "" {
|
||||
logf("Kerberos: %s not found, using default config (KDC discovery via DNS)", krb5cfgPath)
|
||||
krb5cfg = config.New()
|
||||
krb5cfg.LibDefaults.DNSLookupKDC = true
|
||||
} else {
|
||||
var err error
|
||||
krb5cfg, err = config.Load(krb5cfgPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("loading krb5 config: %w", err)
|
||||
}
|
||||
}
|
||||
|
||||
ccPath := ccachePath()
|
||||
ccPath, err := ccachePath()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
logf("Kerberos: loading credential cache from %s", ccPath)
|
||||
ccache, err := credentials.LoadCCache(ccPath)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("no credential cache (%w) — run 'kinit'", err)
|
||||
hint := "run 'kinit'"
|
||||
if runtime.GOOS == "darwin" && os.Getenv("KRB5CCNAME") == "" {
|
||||
hint = fmt.Sprintf("on macOS, run: kinit -c /tmp/krb5cc_%d", os.Getuid())
|
||||
}
|
||||
return nil, fmt.Errorf("no credential cache (%w) — %s", err, hint)
|
||||
}
|
||||
|
||||
cl, err := krb5client.NewFromCCache(ccache, krb5cfg, krb5client.DisablePAFXFAST(true))
|
||||
@@ -224,15 +240,25 @@ func krb5ConfigPath() string {
|
||||
return cmp.Or(os.Getenv("KRB5_CONFIG"), "/etc/krb5.conf")
|
||||
}
|
||||
|
||||
// ccachePath returns the path to the active Kerberos credential cache.
|
||||
// Respects $KRB5CCNAME; strips the "FILE:" prefix if present.
|
||||
// Non-file ccache types (API:, KEYRING:, DIR:) are not supported by gokrb5
|
||||
// and will produce an error when LoadCCache is called.
|
||||
func ccachePath() string {
|
||||
// ccachePath returns the path to the active Kerberos credential cache, or an
|
||||
// error if $KRB5CCNAME names a non-file cache type that gokrb5 cannot read.
|
||||
//
|
||||
// On macOS, kinit defaults to API: caches. Work around it with:
|
||||
//
|
||||
// kinit -c /tmp/krb5cc_$(id -u)
|
||||
func ccachePath() (string, error) {
|
||||
if v := os.Getenv("KRB5CCNAME"); v != "" {
|
||||
return strings.TrimPrefix(v, "FILE:")
|
||||
for _, prefix := range []string{"API:", "KEYRING:", "DIR:", "KCM:"} {
|
||||
if strings.HasPrefix(v, prefix) {
|
||||
return "", fmt.Errorf(
|
||||
"credential cache type %s is not supported (gokrb5 requires a file-based cache)\n"+
|
||||
"hint: re-run kinit with: kinit -c /tmp/krb5cc_%d",
|
||||
prefix, os.Getuid())
|
||||
}
|
||||
}
|
||||
return strings.TrimPrefix(v, "FILE:"), nil
|
||||
}
|
||||
return fmt.Sprintf("/tmp/krb5cc_%d", os.Getuid())
|
||||
return fmt.Sprintf("/tmp/krb5cc_%d", os.Getuid()), nil
|
||||
}
|
||||
|
||||
// ── Password prompt ────────────────────────────────────────────────────────────
|
||||
|
||||
Reference in New Issue
Block a user