Skip to content

Commit fb08c99

Browse files
committed
Migrate library haproxy-spoe-go
Since our library https://github.com/criteo/haproxy-spoe-go has not been updated since a while and that some part of the specification are not well respected (here field engine-id and capability pipelining should be optional), migrate to a better maintained library. Using this library, we could now enable the spop-check in HAProxy for this component.
1 parent 8c77a99 commit fb08c99

File tree

7 files changed

+143
-191
lines changed

7 files changed

+143
-191
lines changed

go.mod

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ go 1.20
44

55
require (
66
github.com/coreos/go-oidc/v3 v3.5.0
7-
github.com/criteo/haproxy-spoe-go v1.0.6
87
github.com/go-ldap/ldap/v3 v3.4.4
8+
github.com/negasus/haproxy-spoe-go v1.0.5
99
github.com/sirupsen/logrus v1.9.0
1010
github.com/spf13/viper v1.15.0
1111
github.com/stretchr/testify v1.8.1
@@ -26,7 +26,6 @@ require (
2626
github.com/magiconair/properties v1.8.7 // indirect
2727
github.com/mitchellh/mapstructure v1.5.0 // indirect
2828
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
29-
github.com/pkg/errors v0.9.1 // indirect
3029
github.com/pmezard/go-difflib v1.0.0 // indirect
3130
github.com/spf13/afero v1.9.3 // indirect
3231
github.com/spf13/cast v1.5.0 // indirect

go.sum

Lines changed: 3 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -59,9 +59,6 @@ github.com/cncf/udpa/go v0.0.0-20200629203442-efcf912fb354/go.mod h1:WmhPx2Nbnht
5959
github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk=
6060
github.com/coreos/go-oidc/v3 v3.5.0 h1:VxKtbccHZxs8juq7RdJntSqtXFtde9YpNpGn0yqgEHw=
6161
github.com/coreos/go-oidc/v3 v3.5.0/go.mod h1:ecXRtV4romGPeO6ieExAsUK9cb/3fp9hXNz1tlv8PIM=
62-
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
63-
github.com/criteo/haproxy-spoe-go v1.0.6 h1:3GDQ8hm/fIkn4wxxI/pN0OoBfKon4ROzvpU5fIriYII=
64-
github.com/criteo/haproxy-spoe-go v1.0.6/go.mod h1:o04s69MOZ7SvPthMtUt/tfn1hcorQQAS/nwzKPBlXQU=
6562
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
6663
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
6764
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
@@ -155,30 +152,27 @@ github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:
155152
github.com/jstemmer/go-junit-report v0.0.0-20190106144839-af01ea7f8024/go.mod h1:6v2b51hI/fHJwM22ozAgKL4VKDeJcHhJFhtBdhmNjmU=
156153
github.com/jstemmer/go-junit-report v0.9.1/go.mod h1:Brl9GWCQeLvo8nXZwPNNblvFj/XSXhF0NWZEnDohbsk=
157154
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
158-
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
159155
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
160156
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
161-
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
162157
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
163158
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
164159
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
165160
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
166-
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
167161
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
168162
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
169163
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
170164
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
165+
github.com/negasus/haproxy-spoe-go v1.0.5 h1:iMUOg/WTdwh4qOD5VUWqXElIG6YefqdOZbTzbVXN8ZU=
166+
github.com/negasus/haproxy-spoe-go v1.0.5/go.mod h1:ZrBizxtx2EeLN37Jkg9w9g32a1AFCJizA8vg46PaAp4=
171167
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
172168
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
173-
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
174169
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
175170
github.com/pkg/sftp v1.13.1/go.mod h1:3HaPG6Dq1ILlpPZRO0HVMrsydcdLt6HRDccSgb87qRg=
176171
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
177172
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
178173
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
179174
github.com/rogpeppe/go-internal v1.3.0/go.mod h1:M8bDsm7K2OlrFYOpmOWEs/qY81heoFRclV5y23lUDJ4=
180175
github.com/rogpeppe/go-internal v1.6.1 h1:/FiVV8dS/e+YqF2JvO3yXRFbBLTIuSDkuC7aBOAvL+k=
181-
github.com/sirupsen/logrus v1.7.0/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0=
182176
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
183177
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
184178
github.com/spf13/afero v1.9.3 h1:41FoI0fD7OR7mGcKE/aOiLkGreyf8ifIOQmJANWogMk=
@@ -338,7 +332,6 @@ golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7w
338332
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
339333
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
340334
golang.org/x/sys v0.0.0-20191001151750-bb3f8db39f24/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
341-
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
342335
golang.org/x/sys v0.0.0-20191204072324-ce4227a45e2e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
343336
golang.org/x/sys v0.0.0-20191228213918-04cbcbbfeed8/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
344337
golang.org/x/sys v0.0.0-20200113162924-86b910548bc1/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -359,7 +352,6 @@ golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7w
359352
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
360353
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
361354
golang.org/x/sys v0.0.0-20210104204734-6f8348627aad/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
362-
golang.org/x/sys v0.0.0-20210113181707-4bcb84eeeb78/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
363355
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
364356
golang.org/x/sys v0.0.0-20210225134936-a50acf3fe073/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
365357
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -538,16 +530,13 @@ google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqw
538530
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
539531
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
540532
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
533+
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127 h1:qIbj1fsPNlZgppZ+VLlY7N33q108Sa+fhmuc+sWQYwY=
541534
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
542-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
543-
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
544535
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
545536
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
546537
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
547538
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
548-
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
549539
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
550-
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
551540
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
552541
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
553542
honnef.co/go/tools v0.0.0-20190102054323-c2f93a96b099/go.mod h1:rf3lG4BRIbNafJWhAfAdb/ePZxsR/4RtNHQocxwk9r4=

internal/agent/agent.go

Lines changed: 28 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -2,69 +2,69 @@ package agent
22

33
import (
44
"log"
5+
"net"
6+
"os"
57

68
"github.com/criteo/haproxy-spoe-auth/internal/auth"
7-
spoe "github.com/criteo/haproxy-spoe-go"
9+
"github.com/negasus/haproxy-spoe-go/action"
10+
"github.com/negasus/haproxy-spoe-go/agent"
11+
"github.com/negasus/haproxy-spoe-go/logger"
12+
"github.com/negasus/haproxy-spoe-go/request"
813
"github.com/sirupsen/logrus"
914
)
1015

1116
// NotAuthenticatedMessage SPOE response stating the user is not authenticated
12-
var NotAuthenticatedMessage = spoe.ActionSetVar{
13-
Name: "is_authenticated",
14-
Scope: spoe.VarScopeSession,
15-
Value: false,
16-
}
17+
var NotAuthenticatedMessage = action.NewSetVar(action.ScopeSession, "is_authenticated", false)
1718

1819
// AuthenticatedMessage SPOE response stating the user is authenticated
19-
var AuthenticatedMessage = spoe.ActionSetVar{
20-
Name: "is_authenticated",
21-
Scope: spoe.VarScopeSession,
22-
Value: true,
23-
}
20+
var AuthenticatedMessage = action.NewSetVar(action.ScopeSession, "is_authenticated", true)
2421

2522
// StartAgent start the agent
2623
func StartAgent(interfaceAddr string, authenticators map[string]auth.Authenticator) {
27-
agent := spoe.New(func(messages *spoe.MessageIterator) ([]spoe.Action, error) {
28-
var actions []spoe.Action
29-
24+
agent := agent.New(func(request *request.Request) {
3025
var authenticated bool = false
3126
var hasError bool = false
3227

33-
for messages.Next() {
34-
msg := messages.Message
35-
logrus.Debugf("new message with name %s received", msg.Name)
28+
for authentifier_name, authentifier := range authenticators {
29+
msg, err := request.Messages.GetByName(authentifier_name)
30+
if err == nil {
31+
logrus.Debugf("new message with name %s received", msg.Name)
3632

37-
authentifier, ok := authenticators[msg.Name]
38-
if ok {
39-
isAuthenticated, replyActions, err := authentifier.Authenticate(&msg)
33+
isAuthenticated, replyActions, err := authentifier.Authenticate(msg)
4034
if err != nil {
4135
logrus.Errorf("unable to authenticate user: %v", err)
4236
hasError = true
4337
break
4438
}
45-
actions = append(actions, replyActions...)
39+
request.Actions = append(request.Actions, replyActions...)
4640

4741
if isAuthenticated {
4842
authenticated = true
4943
}
44+
break
5045
}
5146
}
5247

5348
if hasError {
54-
actions = append(actions, auth.BuildHasErrorMessage())
49+
request.Actions = append(request.Actions, auth.BuildHasErrorMessage())
5550
} else {
5651
if authenticated {
57-
actions = append(actions, AuthenticatedMessage)
52+
request.Actions = append(request.Actions, AuthenticatedMessage)
5853
} else {
59-
actions = append(actions, NotAuthenticatedMessage)
54+
request.Actions = append(request.Actions, NotAuthenticatedMessage)
6055
}
61-
6256
}
63-
return actions, nil
64-
})
57+
}, logger.NewDefaultLog())
58+
59+
listener, err := net.Listen("tcp", interfaceAddr)
60+
if err != nil {
61+
log.Printf("error create listener, %v", err)
62+
os.Exit(1)
63+
}
64+
defer listener.Close()
6565

6666
logrus.Infof("agent starting and listening on %s with %d authenticators", interfaceAddr, len(authenticators))
67-
if err := agent.ListenAndServe(interfaceAddr); err != nil {
67+
if err := agent.Serve(listener); err != nil {
6868
log.Fatal(err)
6969
}
7070
}

internal/auth/authenticator.go

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
package auth
22

3-
import spoe "github.com/criteo/haproxy-spoe-go"
3+
import (
4+
action "github.com/negasus/haproxy-spoe-go/action"
5+
message "github.com/negasus/haproxy-spoe-go/message"
6+
)
47

58
// Authenticator the authenticator interface that can be implemented for LDAP, OAuth2, OIDC or whatever else.
69
type Authenticator interface {
710
// Check whether the user is authenticated by this authenticator
8-
Authenticate(msg *spoe.Message) (bool, []spoe.Action, error)
11+
Authenticate(msg *message.Message) (bool, []action.Action, error)
912
}

internal/auth/authenticator_ldap.go

Lines changed: 23 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import (
66
"fmt"
77
"strings"
88

9-
spoe "github.com/criteo/haproxy-spoe-go"
9+
action "github.com/negasus/haproxy-spoe-go/action"
10+
message "github.com/negasus/haproxy-spoe-go/message"
11+
1012
"github.com/go-ldap/ldap/v3"
1113
"github.com/sirupsen/logrus"
1214
)
@@ -102,39 +104,35 @@ func parseBasicAuth(auth string) (username, password string, err error) {
102104
}
103105

104106
// Authenticate handle an authentication request coming from HAProxy
105-
func (la *LDAPAuthenticator) Authenticate(msg *spoe.Message) (bool, []spoe.Action, error) {
106-
var authorization string
107+
func (la *LDAPAuthenticator) Authenticate(msg *message.Message) (bool, []action.Action, error) {
108+
authorization := ""
107109
group := ""
108110
isGroupProvided := false
109111

110-
for msg.Args.Next() {
111-
arg := msg.Args.Arg
112-
113-
if arg.Name == "authorization" {
114-
var ok bool
115-
authorization, ok = arg.Value.(string)
116-
if !ok {
117-
return false, nil, nil
118-
}
119-
} else if arg.Name == "authorized_group" {
120-
var ok bool
121-
group, ok = arg.Value.(string)
122-
if !ok {
123-
group = ""
124-
}
125-
isGroupProvided = true
112+
authorizationValue, ok := msg.KV.Get("authorization")
113+
if ok {
114+
authorization, ok = authorizationValue.(string)
115+
if !ok {
116+
return false, nil, nil
126117
}
127118
}
128-
129-
if isGroupProvided {
130-
logrus.Debug(fmt.Sprintf("Group is <%s>", group))
131-
}
132-
133119
if authorization == "" {
134120
logrus.Debug("Authorization header is empty")
135121
return false, nil, nil
136122
}
137123

124+
authorizedGroupValue, ok := msg.KV.Get("authorized_group")
125+
if ok {
126+
group, ok = authorizedGroupValue.(string)
127+
if !ok {
128+
group = ""
129+
}
130+
isGroupProvided = true
131+
}
132+
if isGroupProvided {
133+
logrus.Debug(fmt.Sprintf("Group is <%s>", group))
134+
}
135+
138136
username, password, err := parseBasicAuth(authorization)
139137

140138
if err != nil {
@@ -159,5 +157,5 @@ func (la *LDAPAuthenticator) Authenticate(msg *spoe.Message) (bool, []spoe.Actio
159157
}
160158

161159
logrus.Debug("User is authenticated")
162-
return true, []spoe.Action{AuthenticatedUserMessage(username)}, nil
160+
return true, []action.Action{AuthenticatedUserMessage(username)}, nil
163161
}

0 commit comments

Comments
 (0)