gokrb5 Documentation

repository·master·Indexed 21 days ago

https://github.com/jcmturner/gokrb5

A pure Go implementation of the Kerberos protocol providing client and server-side capabilities. Features include SPNEGO authentication for web services, Microsoft Active Directory support (including PAC authorization data), and GSS-API negotiation following RFC 4178. The library supports parsing Keytab, krb5.conf, and client credential cache files, and provides implementations for various encryption and checksum types such as AES and RC4.

Tokens
7.9K
Snippets
30
Records
39
Agent score
71%

What's inside gokrb5

  1. Overview of gokrb5 features

    master

    gokrb5 provides a pure Go, platform-independent Kerberos implementation with the following capabilities:

    Server Side

    • SPNEGO Authentication: HTTP handler wrapper for Kerberos authentication.
    • Microsoft AD Support: Decodes Microsoft AD PAC authorization data.

    Client Side

    • Web Service Authentication: Client for authenticating to SPNEGO Kerberos authenticated web services.
    • Password Management: Ability to change client passwords.

    General Utilities

    • Custom Integration: Kerberos libraries for custom implementations.
    • File Parsing: Support for parsing Keytab files, krb5.conf files, and client credential cache files (e.g., /tmp/krb5cc_$(id -u $(whoami))).
  2. Understand the GSS-API Negotiation Mechanism

    master

    The GSS-API negotiation mechanism (following RFC 4178) allows a client to specify a list of supported security mechanisms to a server in order of preference.

    In gokrb5, the client initiates this process by calling the NewNegTokenInitKrb5 method. This method generates an initial negotiation message that specifies Kerberos v5 as the supported mechanism. This message can optionally include the initial mechanism token for the preferred mechanism (KRB5) to streamline the authentication process.

    Upon receiving the initial message, the server will respond with one of four states:

  3. How GSS-API Negotiation works with Kerberos v5

    master

    GSS-API negotiation follows the mechanism specified in RFC 4178. The process begins with the client sending an initial negotiation message to the server, listing supported mechanisms in order of preference.

    In gokrb5, the NewNegTokenInitKrb5 method generates this initial message. This message specifies that only the Kerberos v5 mechanism is supported and, per the RFC, includes the initial mechanism token for the preferred mechanism (KRB5) within the message to streamline the process.

  4. Implement the SessionMgr interface for SPNEGO

    master

    To support session management in the SPNEGOKRB5Authenticate wrapper, implement the SessionMgr interface. This allows the service to reuse authentication state instead of demanding a new Kerberos exchange on every call.

    type SessionMgr interface {
    	New(w http.ResponseWriter, r *http.Request, k string, v []byte) error
    	Get(r *http.Request, k string) ([]byte, error)
    }
  5. Implement a Kerberised HTTP Service (SPNEGO)

    master

    Wrap an existing http.Handler with spnego.SPNEGOKRB5Authenticate to implement SPNEGO authentication.

    Accessing Authenticated User Data: If authentication succeeds, the request context contains:

    • spnego.CTXKeyAuthenticated: A boolean indicating if the user is authenticated.
    • spnego.CTXKeyCredentials: The user's credentials (implements goidentity.Identity).

    Active Directory Note: If using AD, additional attributes like SIDs are available in the creds.Attributes map under the key credentials.AttributeKeyADCredentials.

    // Wrap a handler
    h := http.HandlerFunc(apphandler)
    http.Handler("/", spnego.SPNEGOKRB5Authenticate(h, &kt, service.Logger(l)))
    
    // Access credentials in handler
    ctx := r.Context()
    if validuser, ok := ctx.Value(spnego.CTXKeyAuthenticated).(bool); ok && validuser {
        if creds, ok := ctx.Value(spnego.CTXKeyCredentials).(goidentity.Identity); ok {
            if ADCreds, ok := creds.Attributes()[credentials.AttributeKeyADCredentials].(credentials.ADCredentials); ok {
                groupSids := ADCreds.GroupMembershipSIDs
            }
        }
    }
  6. Authenticate to a service via Generic Kerberos (AP_REQ)

    master

    For non-HTTP protocols, follow these steps to perform an AP exchange:

    1. Get Service Ticket: Use cl.GetServiceTicket(spn) to retrieve the ticket and session key. This method efficiently uses the cache or requests a new ticket from the KDC.
    2. Generate Authenticator: Create a new authenticator and generate a sequence number and subkey.
    3. Set Checksum: Set the application-specific checksum on the authenticator.
    4. Create AP_REQ: Use messages.NewAPReq to wrap the ticket, key, and authenticator.
    // 1. Get ticket
    tkt, key, err := cl.GetServiceTicket("HTTP/host.test.gokrb5")
    
    // 2. Generate Authenticator
    auth, _ := types.NewAuthenticator(cl.Credentials.Realm, cl.Credentials.CName)
    etype, _ := crypto.GetEtype(key.KeyType)
    auth.GenerateSeqNumberAndSubKey(key.KeyType, etype.GetKeyByteSize())
    
    // 3. Set Checksum
    auth.Cksum = types.Checksum{
    	CksumType: checksumIDint,
    	Checksum:  checksumBytesSlice,
    }
    
    // 4. Create AP_REQ
    APReq, err := messages.NewAPReq(tkt, key, auth)
  7. Implement a Kerberised HTTP Service with SPNEGO

    master

    Use spnego.SPNEGOKRB5Authenticate to wrap an http.Handler. This provides SPNEGO authentication for web services. You must provide a keytab for the SPN. You can optionally provide a Logger and a SessionManager to avoid authenticating on every request.

    import (
    	"net/http"
    	"github.com/jcmturner/gokrb5/v8/spnego"
    	"github.com/jcmturner/gokrb5/v8/service"
    )
    
    // Basic usage
    h := http.HandlerFunc(apphandler)
    http.Handler("/", spnego.SPNEGOKRB5Authenticate(h, &kt))
    
    // With Session Management
    http.Handler("/", spnego.SPNEGOKRB5Authenticate(h, &kt, service.SessionManager(sm)))
  8. Access user credentials and AD attributes in HTTP requests

    master

    When authentication succeeds in an SPNEGO-wrapped handler, the user's credentials are added to the request's context. If using Microsoft Active Directory, you can access AD-specific attributes (like Group Membership SIDs) via the credentials.Attributes map using the credentials.AttributeKeyADCredentials key.

    import (
    	"encoding/json"
    	"github.com/jcmturner/goidentity/identity"
    	"github.com/jcmturner/gokrb5/v8/credentials"
    )
    
    // Get credentials from context
    creds := goidentity.FromHTTPRequestContext(r)
    if creds != nil && creds.Authenticated() {
    	if ADCredsJSON, ok := creds.Attributes()[credentials.AttributeKeyADCredentials]; ok {
    		ADCreds := new(credentials.ADCredentials)
    		err := json.Unmarshal([]byte(ADCredsJSON), ADCreds)
    		if err == nil {
    			// Access fields like ADCreds.GroupMembershipSIDs
    		}
    	}
    }
  9. Configure gokrb5 using krb5.conf

    master

    The gokrb5 libraries use the standard MIT Kerberos krb5.conf format. You can create configuration instances by loading from a file path, a string, an io.Reader, or a bufio.Scanner using the config package.

    import "gopkg.in/jcmturner/gokrb5.v7/config"
    
    cfg, err := config.Load("/path/to/config/file")
    cfg, err := config.NewConfigFromString(krb5Str) // String must have appropriate newline separations
    cfg, err := config.NewConfigFromReader(reader)
    cfg, err := config.NewConfigFromScanner(scanner)
  10. Authenticate to a service using a Generic Kerberos Client

    master

    For non-HTTP protocols, you must manually perform the AP exchange:

    1. Request a service ticket and session key using cl.GetServiceTicket(spn).
    2. Generate an Authenticator with a sequence number and subkey.
    3. Set an application-specific checksum on the authenticator.
    4. Construct the AP_REQ message using messages.NewAPReq and send it to the service.
    // 1. Get ticket
    tkt, key, err := cl.GetServiceTicket("HTTP/host.test.gokrb5")
    
    // 2. Generate Authenticator
    auth, _ := types.NewAuthenticator(cl.Credentials.Realm, cl.Credentials.CName)
    etype, _ := crypto.GetEtype(key.KeyType)
    auth.GenerateSeqNumberAndSubKey(key.KeyType, etype.GetKeyByteSize())
    
    // 3. Set Checksum
    auth.Cksum = types.Checksum{
    	CksumType: checksumIDint,
    	Checksum:  checksumBytesSlice,
    }
    
    // 4. Create AP_REQ
    APReq, err := messages.NewAPReq(tkt, key, auth)
  11. Install and import gokrb5

    master

    gokrb5 is a pure Go Kerberos implementation. It is recommended to use the latest major version (v8).

    v8 (Latest)

    • Dependency Management: Go modules
    • Import Path: import "github.com/jcmturner/gokrb5/v8/{sub-package}"
    • Go Version Support: Formally tested on Go 1.16, 1.17, and 1.18.
    import "github.com/jcmturner/gokrb5/v8/some-sub-package"