Repository: Shopify/sarama
Pull request #1466 (2019-08-22 14:52:31)

Expose kerberos fast negotiation configuration
This PR allows Kerberos to be configured with fast negotiation disable, it is required for certain KDCs (i.e Active directory Kerberos server).





d1egoaz: @rubenvp8510 could you please add some description to the PR to tell why this is important to have, thanks
probot-shopify[bot]: Thank you for your contribution! However, this pull request has not had any activity in the past 90 days and will be closed in 30 days if no updates occur.
If you believe the changes are still valid then please verify your branch has no conflicts with master and rebase if needed. If you are awaiting a (re-)review then please let us know.

camdencheek: Hi @d1egoaz -- this is required when using some versions of Active Directory. It appears to be the problem blocking my issue #1519 as well. 

Patch:
diff --git a/gssapi_kerberos.go b/gssapi_kerberos.go
index 98be0f5..f6877c8 100644
--- a/gssapi_kerberos.go
+++ b/gssapi_kerberos.go
@@ -34,6 +34,7 @@ type GSSAPIConfig struct {
 	Username           string
 	Password           string
 	Realm              string
+	DisablePAFXFAST    bool
 }
 
 type GSSAPIKerberosAuth struct {
diff --git a/kerberos_client.go b/kerberos_client.go
index 91b998f..ebc1141 100644
--- a/kerberos_client.go
+++ b/kerberos_client.go
@@ -19,14 +19,9 @@ func (c *KerberosGoKrb5Client) CName() types.PrincipalName {
 	return c.Credentials.CName()
 }
 
-/*
-*
-* Create kerberos client used to obtain TGT and TGS tokens
-* used gokrb5 library, which is a pure go kerberos client with
-* some GSS-API capabilities, and SPNEGO support. Kafka does not use SPNEGO
-* it uses pure Kerberos 5 solution (RFC-4121 and RFC-4120).
-*
- */
+// NewKerberosClient creates kerberos client used to obtain TGT and TGS tokens.
+// It uses pure go Kerberos 5 solution (RFC-4121 and RFC-4120).
+// uses gokrb5 library underlying which is a pure go kerberos client with some GSS-API capabilities.
 func NewKerberosClient(config *GSSAPIConfig) (KerberosClient, error) {
 	cfg, err := krb5config.Load(config.KerberosConfigPath)
 	if err != nil {
@@ -42,10 +37,10 @@ func createClient(config *GSSAPIConfig, cfg *krb5config.Config) (KerberosClient,
 		if err != nil {
 			return nil, err
 		}
-		client = krb5client.NewClientWithKeytab(config.Username, config.Realm, kt, cfg)
+		client = krb5client.NewClientWithKeytab(config.Username, config.Realm, kt, cfg, krb5client.DisablePAFXFAST(config.DisablePAFXFAST))
 	} else {
 		client = krb5client.NewClientWithPassword(config.Username,
-			config.Realm, config.Password, cfg)
+			config.Realm, config.Password, cfg, krb5client.DisablePAFXFAST(config.DisablePAFXFAST))
 	}
 	return &KerberosGoKrb5Client{*client}, nil
 }


Test patch:
diff --git a/kerberos_client_test.go b/kerberos_client_test.go
index 8af0e17..003da6a 100644
--- a/kerberos_client_test.go
+++ b/kerberos_client_test.go
@@ -84,3 +84,27 @@ func TestCreateWithKeyTab(t *testing.T) {
 		t.Errorf("Expected error:%s, got:%s.", err, expectedErr)
 	}
 }
+
+func TestCreateWithDisablePAFXFAST(t *testing.T) {
+	kerberosConfig, err := krbcfg.NewConfigFromString(testdata.TEST_KRB5CONF)
+	if err != nil {
+		t.Fatal(err)
+	}
+	// Expect to try to create a client with keytab and fails with "o such file or directory" error
+	expectedErr := errors.New("open nonexist.keytab: no such file or directory")
+	clientConfig := NewConfig()
+	clientConfig.Net.SASL.Mechanism = SASLTypeGSSAPI
+	clientConfig.Net.SASL.Enable = true
+	clientConfig.Net.SASL.GSSAPI.ServiceName = "kafka"
+	clientConfig.Net.SASL.GSSAPI.Realm = "EXAMPLE.COM"
+	clientConfig.Net.SASL.GSSAPI.Username = "client"
+	clientConfig.Net.SASL.GSSAPI.AuthType = KRB5_KEYTAB_AUTH
+	clientConfig.Net.SASL.GSSAPI.KeyTabPath = "nonexist.keytab"
+	clientConfig.Net.SASL.GSSAPI.KerberosConfigPath = "/etc/krb5.conf"
+	clientConfig.Net.SASL.GSSAPI.DisablePAFXFAST = true
+
+	_, err = createClient(&clientConfig.Net.SASL.GSSAPI, kerberosConfig)
+	if err.Error() != expectedErr.Error() {
+		t.Errorf("Expected error:%s, got:%s.", err, expectedErr)
+	}
+}