### Install gwim Package Source: https://github.com/akennis/gwim/blob/main/README.md Install the gwim library using the go get command. ```bash go get github.com/akennis/gwim ``` -------------------------------- ### Minimal Secure Server with gwim Source: https://github.com/akennis/gwim/blob/main/README.md This example demonstrates the smallest possible secure server using gwim. It retrieves a TLS certificate from the Windows certificate store, wraps a handler with Kerberos authentication, and starts listening on port 8443. Windows authenticates the current domain user transparently. ```go package main import ( "crypto/tls" "log" "net/http" "github.com/akennis/gwim" ) func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { username, _ := gwim.User(r) w.Write([]byte("Hello, " + username)) }) // Create a Kerberos authentication provider sspiProvider, _ := gwim.NewSSPIProvider() defer sspiProvider.Close() // Retrieve a TLS certificate from the Windows certificate store certSource, _ := gwim.GetWin32Cert("myserver.corp.local", gwim.CertStoreLocalMachine) defer certSource.Close() srv := &http.Server{ Addr: ":8443", Handler: sspiProvider.Middleware(mux), TLSConfig: &tls.Config{ Certificates: []tls.Certificate{certSource.Certificate}, }, } // Windows authenticates the current domain user transparently — // no login prompt, no credentials to manage. log.Fatal(srv.ListenAndServeTLS("", "")) } ``` -------------------------------- ### Run Test Server with Coverage Data Collection Source: https://github.com/akennis/gwim/blob/main/README.md Starts the instrumented test server and sets the GOCOVERDIR environment variable to specify the directory where coverage data will be stored. The server is configured to listen on a specific address and use NTLM authentication. ```powershell mkdir coverage_data $env:GOCOVERDIR="coverage_data" .\testserver.exe --addr 127.0.0.1:8080 --use-ntlm=true ``` -------------------------------- ### Get Refreshing TLS Certificate Function Source: https://github.com/akennis/gwim/blob/main/README.md Provides a tls.Config.GetCertificate callback that automatically refreshes the TLS certificate before it expires, enabling zero-downtime certificate rotation. It also returns an io.Closer to manage background resources. ```go getCertFunc, closer, err := gwim.GetCertificateFunc(certSubject, store, refreshThreshold, retryInterval) if err != nil { // Handle error } // Use getCertFunc in tls.Config.GetCertificate // Call closer.Close() after http.Server.Shutdown returns ``` -------------------------------- ### Get TLS Certificate from Windows Store Source: https://github.com/akennis/gwim/blob/main/README.md Retrieves a TLS certificate from the Windows certificate store by its Common Name. The certificate is validated for expiry, Extended Key Usage, and issuer chain. The returned CertificateSource can be used directly in tls.Config.Certificates. ```go certSource, err := gwim.GetWin32Cert(certSubject, store) if err != nil { // Handle error } // Use certSource.Certificate in tls.Config.Certificates // Call certSource.Close() on server shutdown ``` -------------------------------- ### Create SSPI Provider (Kerberos) Source: https://github.com/akennis/gwim/blob/main/README.md Instantiates an SSPI provider using Kerberos, the recommended option for production environments. Errors during credential acquisition are returned at startup. ```go sspiProvider, err := gwim.NewSSPIProvider() ``` -------------------------------- ### Build Instrumented Test Server Source: https://github.com/akennis/gwim/blob/main/README.md Builds the test server executable with Go's code coverage instrumentation enabled. Ensure you are in the correct directory for the test server's main package. ```powershell go build -cover -o testserver.exe ./integration_tests/cmd/testserver/main.go ``` -------------------------------- ### Create SSPI Provider (NTLM) Source: https://github.com/akennis/gwim/blob/main/README.md Instantiates an SSPI provider using NTLM, suitable for local development or non-domain scenarios where Kerberos loopback authentication is not feasible. Errors during credential acquisition are returned at startup. ```go sspiProvider, err := gwim.NewSSPIProvider(gwim.WithNTLM()) ``` -------------------------------- ### New LDAP Provider Initialization Source: https://github.com/akennis/gwim/blob/main/README.md Initializes a new LDAP provider with specified options. This function performs a synchronous connectivity check, including TLS connection and authentication, before returning. It's recommended to wrap your handlers with the middleware provided by this provider. ```go ldapProvider, err := gwim.NewLDAPProvider( gwim.WithLDAPAddress("dc01.corp.local:636"), gwim.WithLDAPUsersDN("OU=Users,DC=corp,DC=local"), gwim.WithLDAPServiceAccountSPN("LDAP/DC1.corp.local"), ) if err != nil { log.Fatalf("failed to create LDAP provider: %v", err) } // Wrap the LDAP-wrapped handler with SSPI (SSPI runs first) handler = sspiProvider.Middleware(ldapProvider.Middleware(mux)) // Or with a router router.Use(sspiProvider.Middleware) router.Use(ldapProvider.Middleware) ``` -------------------------------- ### NewSSPIProvider Source: https://github.com/akennis/gwim/blob/main/README.md Acquires Windows SSPI credentials and returns a provider. This function can be used to create either a Kerberos or NTLM provider, with options for custom error handling. It's recommended to call `Close()` on the returned provider during server shutdown. ```APIDOC ## `NewSSPIProvider` ```go sspiProvider, err := gwim.NewSSPIProvider(opts ...SSPIOption) ``` ### Description Acquires Windows SSPI credentials and returns a provider. Any credential acquisition error is surfaced here at startup rather than on the first request. ### Usage ```go // Kerberos (production default) sspiProvider, err := gwim.NewSSPIProvider() // NTLM (local / non-domain development) sspiProvider, err := gwim.NewSSPIProvider(gwim.WithNTLM()) // With custom error handling sspiProvider, err := gwim.NewSSPIProvider( gwim.WithNTLM(), gwim.WithSSPIErrorHandlers(gwim.AuthErrorHandlers{ OnGeneralError: myErrorHandler, }), ) ``` ### Options #### `SSPIOption` functions: - `WithNTLM()`: Use NTLM instead of Kerberos. Required for non-domain or localhost scenarios. - `WithSSPIErrorHandlers(h AuthErrorHandlers)`: Override default error responses. ### Lifecycle Call `sspiProvider.Close()` on server shutdown to release Windows credential handles. ``` -------------------------------- ### Run Kerberos Integration Tests Source: https://github.com/akennis/gwim/blob/main/README.md Executes Kerberos integration tests against a running test server on a different machine. Requires Kerberos to be set up in an Active Directory domain. ```go go test -tags=integration -v ./integration_tests -server-url http://:8080 -auth-mode kerberos ``` -------------------------------- ### Build NTLM Test Server Source: https://github.com/akennis/gwim/blob/main/README.md Builds the test server executable for NTLM integration tests. ```powershell go build -o testserver.exe ./integration_tests/cmd/testserver/main.go ``` -------------------------------- ### Configure NTLM Connection Tracking Source: https://github.com/akennis/gwim/blob/main/README.md Configures an http.Server to track NTLM connection state using a ConnContext callback. This is essential for NTLM's two-step token exchange across keep-alive connections and is not required for Kerberos. ```go gwim.ConfigureNTLM(server *http.Server) ``` -------------------------------- ### Run NTLM Integration Tests Source: https://github.com/akennis/gwim/blob/main/README.md Executes NTLM integration tests against a running test server. ```go go test -tags=integration -v ./integration_tests -server-url http://127.0.0.1:8080 -auth-mode ntlm ``` -------------------------------- ### Create SSPI Provider with Custom Error Handlers Source: https://github.com/akennis/gwim/blob/main/README.md Instantiates an SSPI provider with NTLM enabled and custom error handlers for specific authentication errors. This allows for tailored error responses instead of the defaults. ```go sspiProvider, err := gwim.NewSSPIProvider( gwim.WithNTLM(), gwim.WithSSPIErrorHandlers(gwim.AuthErrorHandlers{ OnGeneralError: myErrorHandler, }), ) ``` -------------------------------- ### Apply SSPI Provider Middleware (Router) Source: https://github.com/akennis/gwim/blob/main/README.md Registers the SSPI provider's middleware with a router that supports the standard Go middleware pattern (e.g., using a `Use()` method). This ensures authentication is applied to all routes handled by the router. ```go // Any router with Use() router.Use(sspiProvider.Middleware) ``` -------------------------------- ### GetWin32Cert Source: https://github.com/akennis/gwim/blob/main/README.md Retrieves a TLS certificate from the Windows certificate store, validating its properties and issuer chain. The returned certificate is ready for use in `tls.Config`. ```APIDOC ## GetWin32Cert ### Description Retrieves a TLS certificate from the specified Windows certificate store based on its Common Name (CN). The certificate is validated for expiration, server authentication extended key usage, and its issuer chain. ### Method `GetWin32Cert(certSubject string, store CertStore) (*CertificateSource, error)` ### Parameters - **`certSubject`** (string): The Common Name (CN) of the certificate to retrieve. - **`store`** (`CertStore`): The certificate store to search in. Use `CertStoreLocalMachine` or `CertStoreCurrentUser`. ### Return Value - `*CertificateSource`: A struct containing the `tls.Certificate` ready for use in `tls.Config.Certificates`. - `error`: An error if the certificate cannot be retrieved or validated. ### Lifecycle Call `Close()` on the returned `CertificateSource` when it's no longer needed (e.g., on server shutdown) to release Windows store handles. ``` -------------------------------- ### Apply SSPI Provider Middleware (net/http) Source: https://github.com/akennis/gwim/blob/main/README.md Applies the SSPI provider's middleware to a standard net/http handler. This integrates the authentication logic into the request processing pipeline. ```go // Standard net/http handler := sspiProvider.Middleware(mux) ``` -------------------------------- ### Restoring User Identity from Session Source: https://github.com/akennis/gwim/blob/main/README.md Demonstrates how to restore a user's identity, including their groups, from a session store. This is useful for avoiding re-authentication and LDAP lookups on every request. Ensure this runs before the SSPI middleware. ```go // In your session middleware, before the SSPI middleware runs: if sessionUser, ok := getSession(r); ok { r = gwim.SetUser(r, sessionUser) r = gwim.SetUserGroups(r, sessionUser.Groups) } ``` -------------------------------- ### ConfigureNTLM Source: https://github.com/akennis/gwim/blob/main/README.md Configures an http.Server with the necessary ConnContext callback for NTLM connection tracking. This is essential for NTLM's connection-oriented authentication state management, especially for correlating token exchanges across keep-alive connections. This function is only required when using NTLM. ```APIDOC ## `ConfigureNTLM` ```go gwim.ConfigureNTLM(server *http.Server) ``` ### Description Configures the `http.Server` with the `ConnContext` callback required for NTLM connection tracking. NTLM is connection-oriented — each TCP connection carries its own authentication state. This function assigns a unique ID to every connection so the NTLM handler can correlate the two-step token exchange across requests on the same keep-alive connection. **Only required when using NTLM; not needed for Kerberos.** ``` -------------------------------- ### Generate HTML Coverage Report Source: https://github.com/akennis/gwim/blob/main/README.md Generates a detailed HTML report of the code coverage. This involves first formatting the raw coverage data into a text format and then using the go tool cover command to create the HTML output. ```powershell go tool covdata textfmt -i=coverage_data -o coverage.out go tool cover '-html=coverage.out' ``` -------------------------------- ### View Coverage Percentage Source: https://github.com/akennis/gwim/blob/main/README.md Calculates and displays the overall code coverage percentage from the data collected in the specified directory. This command is run after the integration tests have completed and the server has been stopped. ```powershell go tool covdata percent -i=coverage_data ``` -------------------------------- ### GetCertificateFunc Source: https://github.com/akennis/gwim/blob/main/README.md Provides a `tls.Config.GetCertificate` callback that dynamically retrieves and refreshes TLS certificates from the Windows certificate store, enabling zero-downtime certificate rotation. ```APIDOC ## GetCertificateFunc ### Description Returns a `tls.Config.GetCertificate` function that automatically fetches and refreshes TLS certificates from the Windows certificate store. It supports background refreshing when certificates approach expiry, facilitating zero-downtime rotations. ### Method `GetCertificateFunc(certSubject string, store CertStore, refreshThreshold, retryInterval time.Duration) (func(*tls.ClientHelloInfo) (*tls.Certificate, error), io.Closer, error)` ### Parameters - **`certSubject`** (string): The Common Name (CN) of the certificate. - **`store`** (`CertStore`): The certificate store (`CertStoreLocalMachine` or `CertStoreCurrentUser`). - **`refreshThreshold`** (`time.Duration`): The duration before expiry at which the certificate should be refreshed. Use `DefaultRefreshThreshold` for standard value. - **`retryInterval`** (`time.Duration`): The interval for retrying certificate refreshes. Use `DefaultRetryInterval` for standard value. ### Return Value - `func(*tls.ClientHelloInfo) (*tls.Certificate, error)`: A callback function suitable for `tls.Config.GetCertificate`. - `io.Closer`: An `io.Closer` that must be called after `http.Server.Shutdown` returns to release resources. - `error`: An error if the initial setup fails. ``` -------------------------------- ### NewLDAPProvider Source: https://github.com/akennis/gwim/blob/main/README.md Creates a new LDAP provider that enriches authenticated requests with Active Directory group memberships. It performs a synchronous connectivity check and authentication at startup. The provider maintains a connection pool for runtime operations. ```APIDOC ## NewLDAPProvider ### Description Initializes a new LDAP provider. This provider enriches the request context with the user's Active Directory group memberships by querying the `tokenGroups` attribute. Group memberships are returned as LDAP Distinguished Names (DNs). ### Method `gwim.NewLDAPProvider(opts ...LDAPOption) (*LDAPProvider, error)` ### Parameters #### Options (`LDAPOption`) - **`WithLDAPAddress(addr string)`**: Specifies the host and port of the LDAP/domain controller. LDAPS is always used. - **`WithLDAPUsersDN(dn string)`**: Sets the Distinguished Name of the Organizational Unit containing user accounts. - **`WithLDAPServiceAccountSPN(spn string)`**: Provides the Service Principal Name (SPN) of the LDAP service account for GSSAPI bind. - **`WithLDAPTimeout(d time.Duration)`**: Configures the per-operation timeout. Defaults to `DefaultLdapTimeout` (5s). - **`WithLDAPConnectionTTL(d time.Duration)`**: Sets the maximum lifetime for a pooled connection. Defaults to `DefaultLdapTTL` (1h). - **`WithLDAPErrorHandlers(h AuthErrorHandlers)`**: Allows overriding the default error response handlers. ### Startup Validation `NewLDAPProvider` performs a synchronous connectivity check, including a TLS connection (LDAPS), GSSAPI/Kerberos bind, and a RootDSE search. Errors are returned at startup. ### Runtime Behavior The provider uses an internal connection pool (capacity: 10). Each pooled connection is health-checked before use and discarded if it fails or exceeds its TTL. ### Lifecycle Call `ldapProvider.Close()` on server shutdown to drain the connection pool and release resources. ### Request Example ```go ldapProvider, err := gwim.NewLDAPProvider( gwim.WithLDAPAddress("dc01.corp.local:636"), gwim.WithLDAPUsersDN("OU=Users,DC=corp,DC=local"), gwim.WithLDAPServiceAccountSPN("LDAP/DC1.corp.local"), ) if err != nil { log.Fatalf("failed to create LDAP provider: %v", err) } // Example of wrapping an HTTP handler handler = ldapProvider.Middleware(handler) ``` ``` -------------------------------- ### Run NTLM Test Server Source: https://github.com/akennis/gwim/blob/main/README.md Runs the NTLM test server locally on a specified address and port. ```powershell .\testserver.exe --addr 127.0.0.1:8080 --use-ntlm=true ``` -------------------------------- ### Request Context Helpers Source: https://github.com/akennis/gwim/blob/main/README.md Provides functions to retrieve and set user and group information within an HTTP request's context, useful for session management and avoiding re-authentication. ```APIDOC ## Request Context Helpers ### Description These functions facilitate the management of user identity and group memberships within an `http.Request`'s context. They are particularly useful for restoring user sessions without re-authenticating or re-querying LDAP on every request. ### Functions - **`User(r *http.Request) (string, bool)`**: Retrieves the authenticated username from the request context. Returns the username and `true` if found, otherwise an empty string and `false`. - **`SetUser(r *http.Request, username string) *http.Request`**: Injects a username into the request context. If a username is already present, authentication is skipped, allowing for session restoration. - **`UserGroups(r *http.Request) ([]string, bool)`**: Retrieves the user's group memberships (as LDAP DNs) from the request context. Returns a slice of group DNs and `true` if found, otherwise an empty slice and `false`. - **`SetUserGroups(r *http.Request, groups []string) *http.Request`**: Injects group memberships into the request context. If groups are already present, LDAP lookups are skipped, useful for restoring cached groups. ### Usage Example (Session Restoration) ```go // In your session middleware, before SSPI middleware: if sessionUser, ok := getSession(r); ok { r = gwim.SetUser(r, sessionUser.Username) r = gwim.SetUserGroups(r, sessionUser.Groups) } ``` ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.