Skip to content

Commit e91b8d7

Browse files
committed
add sasl_ssl support:
* add security_protocol to authConfig. a single value, SASL_SSL, is supported for now. this allows one to enable TLS support * add sasl_mechanism to authConfig. currently we check for PLAIN and SCRAM-SHA256/SCRAM-SHA512 * setupAuthTLS can now handle both client certs and the old "1 way" setup
1 parent e062ed5 commit e91b8d7

4 files changed

Lines changed: 86 additions & 31 deletions

File tree

common.go

Lines changed: 40 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -164,6 +164,24 @@ func randomString(length int) string {
164164
return fmt.Sprintf("%x", buf)[:length]
165165
}
166166

167+
func setupSaslMechanism(auth authConfig, saramaCfg *sarama.Config) (error) {
168+
switch strings.ToLower(auth.SASLMechanism) {
169+
case "plain", "":
170+
saramaCfg.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypePlaintext)
171+
return nil
172+
case "scram-sha512":
173+
saramaCfg.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: SHA512} }
174+
saramaCfg.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypeSCRAMSHA512)
175+
return nil
176+
case "scram-sha256":
177+
saramaCfg.Net.SASL.SCRAMClientGeneratorFunc = func() sarama.SCRAMClient { return &XDGSCRAMClient{HashGeneratorFcn: SHA256} }
178+
saramaCfg.Net.SASL.Mechanism = sarama.SASLMechanism(sarama.SASLTypeSCRAMSHA256)
179+
return nil
180+
default:
181+
return fmt.Errorf("Unsupported auth sasl mechanism: %#v", auth.SASLMechanism)
182+
}
183+
}
184+
167185
// setupCerts takes the paths to a tls certificate, CA, and certificate key in
168186
// a PEM format and returns a constructed tls.Config object.
169187
func setupCerts(certPath, caPath, keyPath string) (*tls.Config, error) {
@@ -207,6 +225,8 @@ type authConfig struct {
207225
ClientCertKey string `json:"client-certificate-key"`
208226
SASLPlainUser string `json:"sasl_plain_user"`
209227
SASLPlainPassword string `json:"sasl_plain_password"`
228+
SASLMechanism string `json:"sasl_mechanism"`
229+
SecurityProtocol string `json:"security_protocol"`
210230
}
211231

212232
func setupAuth(auth authConfig, saramaCfg *sarama.Config) error {
@@ -218,7 +238,7 @@ func setupAuth(auth authConfig, saramaCfg *sarama.Config) error {
218238
case "TLS":
219239
return setupAuthTLS(auth, saramaCfg)
220240
case "TLS-1way":
221-
return setupAuthTLS1Way(auth, saramaCfg)
241+
return setupAuthTLS(auth, saramaCfg)
222242
case "SASL":
223243
return setupSASL(auth, saramaCfg)
224244
default:
@@ -230,38 +250,24 @@ func setupSASL(auth authConfig, saramaCfg *sarama.Config) error {
230250
saramaCfg.Net.SASL.Enable = true
231251
saramaCfg.Net.SASL.User = auth.SASLPlainUser
232252
saramaCfg.Net.SASL.Password = auth.SASLPlainPassword
233-
return nil
234-
}
253+
err := setupSaslMechanism(auth, saramaCfg)
235254

236-
func setupAuthTLS1Way(auth authConfig, saramaCfg *sarama.Config) error {
237-
saramaCfg.Net.TLS.Enable = true
238-
saramaCfg.Net.TLS.Config = &tls.Config{}
239-
240-
if auth.CACert == "" {
241-
return nil
242-
}
243-
244-
caString, err := os.ReadFile(auth.CACert)
245255
if err != nil {
246-
return fmt.Errorf("failed to read ca-certificate err=%v", err)
256+
return err;
247257
}
248258

249-
caPool := x509.NewCertPool()
250-
ok := caPool.AppendCertsFromPEM(caString)
251-
if !ok {
252-
failf("unable to add ca-certificate at %s to certificate pool", auth.CACert)
259+
if (strings.EqualFold(auth.SecurityProtocol, "SASL_SSL")) {
260+
return setupAuthTLS(auth, saramaCfg)
253261
}
254-
255-
tlsCfg := &tls.Config{RootCAs: caPool}
256-
tlsCfg.BuildNameToCertificate()
257-
258-
saramaCfg.Net.TLS.Config = tlsCfg
259262
return nil
260263
}
261264

262265
func setupAuthTLS(auth authConfig, saramaCfg *sarama.Config) error {
263-
if auth.CACert == "" || auth.ClientCert == "" || auth.ClientCertKey == "" {
264-
return fmt.Errorf("client-certificate, client-certificate-key and ca-certificate are required - got auth=%#v", auth)
266+
saramaCfg.Net.TLS.Enable = true
267+
saramaCfg.Net.TLS.Config = &tls.Config{}
268+
269+
if auth.CACert == "" {
270+
return nil
265271
}
266272

267273
caString, err := os.ReadFile(auth.CACert)
@@ -275,17 +281,20 @@ func setupAuthTLS(auth authConfig, saramaCfg *sarama.Config) error {
275281
failf("unable to add ca-certificate at %s to certificate pool", auth.CACert)
276282
}
277283

278-
clientCert, err := tls.LoadX509KeyPair(auth.ClientCert, auth.ClientCertKey)
279-
if err != nil {
280-
return err
281-
}
284+
var tlsCfg *tls.Config
285+
if auth.ClientCert != "" && auth.ClientCertKey != "" {
286+
clientCert, err := tls.LoadX509KeyPair(auth.ClientCert, auth.ClientCertKey)
287+
if err != nil {
288+
return err
289+
}
290+
tlsCfg = &tls.Config{RootCAs: caPool, Certificates: []tls.Certificate{clientCert}}
291+
} else {
292+
tlsCfg = &tls.Config{RootCAs: caPool}
282293

283-
tlsCfg := &tls.Config{RootCAs: caPool, Certificates: []tls.Certificate{clientCert}}
294+
}
284295
tlsCfg.BuildNameToCertificate()
285296

286-
saramaCfg.Net.TLS.Enable = true
287297
saramaCfg.Net.TLS.Config = tlsCfg
288-
289298
return nil
290299
}
291300

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ require (
77
github.com/davecgh/go-spew v1.1.1
88
github.com/markusmobius/go-dateparser v1.2.1
99
github.com/stretchr/testify v1.8.4
10+
github.com/xdg-go/scram v1.1.2
1011
golang.org/x/crypto v0.13.0
1112
)
1213

@@ -36,6 +37,8 @@ require (
3637
github.com/rogpeppe/go-internal v1.11.0 // indirect
3738
github.com/tetratelabs/wazero v1.5.0 // indirect
3839
github.com/wasilibs/go-re2 v1.4.0 // indirect
40+
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
41+
github.com/xdg-go/stringprep v1.0.4 // indirect
3942
golang.org/x/exp v0.0.0-20230905200255-921286631fa9 // indirect
4043
golang.org/x/net v0.15.0 // indirect
4144
golang.org/x/sys v0.12.0 // indirect

go.sum

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,12 @@ github.com/wasilibs/go-re2 v1.4.0 h1:Jp6BM8G/zajgY1BCQUm3i7oGMdR1gA5EBv87wGd2ysc
7777
github.com/wasilibs/go-re2 v1.4.0/go.mod h1:hLzlKjEgON+17hWjikLx8hJBkikyjQH/lsqCy9t6tIY=
7878
github.com/wasilibs/nottinygc v0.4.0 h1:h1TJMihMC4neN6Zq+WKpLxgd9xCFMw7O9ETLwY2exJQ=
7979
github.com/wasilibs/nottinygc v0.4.0/go.mod h1:oDcIotskuYNMpqMF23l7Z8uzD4TC0WXHK8jetlB3HIo=
80+
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
81+
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
82+
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
83+
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
84+
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
85+
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
8086
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
8187
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
8288
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
@@ -114,6 +120,7 @@ golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
114120
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
115121
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
116122
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
123+
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
117124
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
118125
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k=
119126
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=

scram_client.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package main
2+
3+
import (
4+
"crypto/sha256"
5+
"crypto/sha512"
6+
"hash"
7+
8+
"github.com/xdg-go/scram"
9+
)
10+
11+
var SHA256 scram.HashGeneratorFcn = func() hash.Hash { return sha256.New() }
12+
var SHA512 scram.HashGeneratorFcn = func() hash.Hash { return sha512.New() }
13+
14+
type XDGSCRAMClient struct {
15+
*scram.Client
16+
*scram.ClientConversation
17+
scram.HashGeneratorFcn
18+
}
19+
20+
func (x *XDGSCRAMClient) Begin(userName, password, authzID string) (err error) {
21+
x.Client, err = x.HashGeneratorFcn.NewClient(userName, password, authzID)
22+
if err != nil {
23+
return err
24+
}
25+
x.ClientConversation = x.Client.NewConversation()
26+
return nil
27+
}
28+
29+
func (x *XDGSCRAMClient) Step(challenge string) (response string, err error) {
30+
response, err = x.ClientConversation.Step(challenge)
31+
return
32+
}
33+
34+
func (x *XDGSCRAMClient) Done() bool {
35+
return x.ClientConversation.Done()
36+
}

0 commit comments

Comments
 (0)