Attempt to support unconfigured kerberos and weird Mac cred cache
This commit is contained in:
@@ -10,6 +10,7 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/signal"
|
"os/signal"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
"runtime"
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"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) {
|
func credFetchKerberos(url string, logf func(string, ...any)) ([]byte, error) {
|
||||||
krb5cfgPath := krb5ConfigPath()
|
krb5cfgPath := krb5ConfigPath()
|
||||||
logf("Kerberos: loading config from %s", krb5cfgPath)
|
logf("Kerberos: loading config from %s", krb5cfgPath)
|
||||||
krb5cfg, err := config.Load(krb5cfgPath)
|
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 {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("loading krb5 config: %w", err)
|
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)
|
logf("Kerberos: loading credential cache from %s", ccPath)
|
||||||
ccache, err := credentials.LoadCCache(ccPath)
|
ccache, err := credentials.LoadCCache(ccPath)
|
||||||
if err != nil {
|
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))
|
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")
|
return cmp.Or(os.Getenv("KRB5_CONFIG"), "/etc/krb5.conf")
|
||||||
}
|
}
|
||||||
|
|
||||||
// ccachePath returns the path to the active Kerberos credential cache.
|
// ccachePath returns the path to the active Kerberos credential cache, or an
|
||||||
// Respects $KRB5CCNAME; strips the "FILE:" prefix if present.
|
// error if $KRB5CCNAME names a non-file cache type that gokrb5 cannot read.
|
||||||
// Non-file ccache types (API:, KEYRING:, DIR:) are not supported by gokrb5
|
//
|
||||||
// and will produce an error when LoadCCache is called.
|
// On macOS, kinit defaults to API: caches. Work around it with:
|
||||||
func ccachePath() string {
|
//
|
||||||
|
// kinit -c /tmp/krb5cc_$(id -u)
|
||||||
|
func ccachePath() (string, error) {
|
||||||
if v := os.Getenv("KRB5CCNAME"); v != "" {
|
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 fmt.Sprintf("/tmp/krb5cc_%d", os.Getuid())
|
}
|
||||||
|
return strings.TrimPrefix(v, "FILE:"), nil
|
||||||
|
}
|
||||||
|
return fmt.Sprintf("/tmp/krb5cc_%d", os.Getuid()), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// ── Password prompt ────────────────────────────────────────────────────────────
|
// ── Password prompt ────────────────────────────────────────────────────────────
|
||||||
|
|||||||
Reference in New Issue
Block a user