This is a port of the PyKerberos library in Go. The main motivation for this library was to provide HTTP client authentication using Kerberos. The khttp package provides a transport that authenticates all outgoing requests using SPNEGO (negotiate authentication) http://tools.ietf.org/html/rfc4559.
The C code is adapted from PyKerberos http://calendarserver.org/wiki/PyKerberos.
Note: You need the have the krb5-libs/GSSAPI packages installed for your OS.
Install using go tools:
$ go get github.com/ubccr/kerby
To run the unit tests you must have a valid Kerberos setup on the test machine and you should ensure that you have valid Kerberos tickets (run 'klist' on the command line). If you're authentication using a client keytab file you can optionally export the env variable KRB5_CLIENT_KTNAME:
$ export KRB5_CLIENT_KTNAME=/path/to/client.keytab $ export KERBY_TEST_SERVICE="service@REALM" $ export KERBY_TEST_PRINC="princ@REALM" $ go test
Example HTTP Kerberos client authentication using a client keytab file:
package main import ( "fmt" "io/ioutil" "bytes" "net/http" "github.com/ubccr/kerby/khttp" ) func main() { payload := []byte(`{"method":"hello_world"}`) req, err := http.NewRequest( "POST", "https://server.example.com/json", bytes.NewBuffer(payload)) req.Header.Set("Content-Type", "application/json") t := &khttp.Transport{ KeyTab: "/path/to/client.keytab", Principal: "principal@REALM"} client := &http.Client{Transport: t} res, err := client.Do(req) if err != nil { panic(err) } defer res.Body.Close() data, err := ioutil.ReadAll(res.Body) if err != nil { panic(err) } fmt.Printf("%d\n", res.StatusCode) fmt.Printf("%s", data) }
Example HTTP handler supporting Kerberose authentication:
func handler(w http.ResponseWriter, req *http.Request) { authReq := strings.Split(req.Header.Get(authorizationHeader), " ") if len(authReq) != 2 || authReq[0] != negotiateHeader { w.Header().Set(wwwAuthenticateHeader, negotiateHeader) http.Error(w, "Invalid authorization header", http.StatusUnauthorized) return } ks := new(kerby.KerbServer) err := ks.Init("") if err != nil { log.Printf("KerbServer Init Error: %s", err.Error()) http.Error(w, err.Error(), http.StatusInternalServerError) return } defer ks.Clean() err = ks.Step(authReq[1]) w.Header().Set(wwwAuthenticateHeader, negotiateHeader+" "+ks.Response()) if err != nil { log.Printf("KerbServer Step Error: %s", err.Error()) http.Error(w, err.Error(), http.StatusUnauthorized) return } user := ks.UserName() fmt.Fprintf(w, "Hello, %s", user) }
Example adding Kerberos authentication to an http.FileServer using khttp.Handler:
package main import ( "github.com/ubccr/kerby/khttp" "log" "net/http" ) func main() { http.Handle("/", khttp.Handler(http.FileServer(http.Dir("/tmp")))) log.Fatal(http.ListenAndServe(":8000", nil)) }
Kerby is released under the Apache 2.0 License. See the LICENSE file.