Skip to content

Commit b54bb47

Browse files
authored
Merge pull request #94 from mutablelogic/v5
Updated server to add LDAP
2 parents 68af4ce + 0ba455a commit b54bb47

File tree

20 files changed

+1403
-1
lines changed

20 files changed

+1403
-1
lines changed

cmd/server/main.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
auth "github.com/mutablelogic/go-server/pkg/auth/cmd"
99
certmanager "github.com/mutablelogic/go-server/pkg/cert/cmd"
1010
cmd "github.com/mutablelogic/go-server/pkg/cmd"
11+
ldap "github.com/mutablelogic/go-server/pkg/ldap/cmd"
1112
pgmanager "github.com/mutablelogic/go-server/pkg/pgmanager/cmd"
1213
pgqueue "github.com/mutablelogic/go-server/pkg/pgqueue/cmd"
1314
)
@@ -31,6 +32,10 @@ type CLI struct {
3132
auth.UserCommands
3233
auth.TokenCommands
3334
auth.AuthCommands
35+
36+
// LDAP commands
37+
LDAP struct{ ldap.ObjectCommands } `cmd:""`
38+
3439
VersionCommands
3540
}
3641

cmd/server/service.go

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ import (
2525
cert "github.com/mutablelogic/go-server/pkg/cert/config"
2626
httprouter "github.com/mutablelogic/go-server/pkg/httprouter/config"
2727
httpserver "github.com/mutablelogic/go-server/pkg/httpserver/config"
28+
ldap "github.com/mutablelogic/go-server/pkg/ldap/config"
2829
logger "github.com/mutablelogic/go-server/pkg/logger/config"
2930
pg "github.com/mutablelogic/go-server/pkg/pgmanager/config"
3031
pgqueue "github.com/mutablelogic/go-server/pkg/pgqueue/config"
@@ -199,6 +200,20 @@ func (cmd *ServiceRunCommand) Run(app server.Cmd) error {
199200

200201
return nil
201202
}))
203+
204+
err = errors.Join(err, provider.Load("ldap", "main", func(ctx context.Context, label string, config server.Plugin) error {
205+
ldap := config.(*ldap.Config)
206+
207+
// Set the router
208+
if router, ok := ref.Provider(ctx).Task(ctx, "httprouter.main").(server.HTTPRouter); !ok || router == nil {
209+
return httpresponse.ErrInternalError.With("Invalid router")
210+
} else {
211+
ldap.Router = router
212+
}
213+
214+
return nil
215+
}))
216+
202217
if err != nil {
203218
return err
204219
}

go.mod

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ require (
66
github.com/alecthomas/kong v1.10.0
77
github.com/djthorpe/go-marshaler v1.0.0
88
github.com/djthorpe/go-pg v1.0.6
9+
github.com/go-ldap/ldap/v3 v3.4.11
910
github.com/golang-jwt/jwt/v5 v5.2.2
1011
github.com/mutablelogic/go-client v1.0.12
1112
github.com/stretchr/testify v1.10.0
@@ -14,6 +15,7 @@ require (
1415
require (
1516
dario.cat/mergo v1.0.0 // indirect
1617
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 // indirect
18+
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
1719
github.com/Microsoft/go-winio v0.6.2 // indirect
1820
github.com/cenkalti/backoff/v4 v4.2.1 // indirect
1921
github.com/containerd/containerd v1.7.27 // indirect
@@ -27,6 +29,7 @@ require (
2729
github.com/docker/go-connections v0.5.0 // indirect
2830
github.com/docker/go-units v0.5.0 // indirect
2931
github.com/felixge/httpsnoop v1.0.4 // indirect
32+
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 // indirect
3033
github.com/go-logr/logr v1.4.2 // indirect
3134
github.com/go-logr/stdr v1.2.2 // indirect
3235
github.com/go-ole/go-ole v1.2.6 // indirect

go.sum

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@ github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24 h1:bvDV9
44
github.com/AdaLogics/go-fuzz-headers v0.0.0-20230811130428-ced1acdcaa24/go.mod h1:8o94RPi1/7XTJvwPpRSzSUedZrtlirdB3r9Z20bi2f8=
55
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1 h1:UQHMgLO+TxOElx5B5HZ4hJQsoJ/PvUvKRhJHDQXO8P8=
66
github.com/Azure/go-ansiterm v0.0.0-20210617225240-d185dfc1b5a1/go.mod h1:xomTg63KZ2rFqZQzSB4Vz2SUXa1BpHTVz9L5PTmPC4E=
7+
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
8+
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
79
github.com/Microsoft/go-winio v0.6.2 h1:F2VQgta7ecxGYO8k3ZZz3RS8fVIXVxONVUPlNERoyfY=
810
github.com/Microsoft/go-winio v0.6.2/go.mod h1:yd8OoFMLzJbo9gZq8j5qaps8bJ9aShtEA8Ipt1oGCvU=
911
github.com/alecthomas/assert/v2 v2.11.0 h1:2Q9r3ki8+JYXvGsDyBXwH3LcJ+WK5D0gc5E8vS6K3D0=
@@ -12,6 +14,8 @@ github.com/alecthomas/kong v1.10.0 h1:8K4rGDpT7Iu+jEXCIJUeKqvpwZHbsFRoebLbnzlmrp
1214
github.com/alecthomas/kong v1.10.0/go.mod h1:p2vqieVMeTAnaC83txKtXe8FLke2X07aruPWXyMPQrU=
1315
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
1416
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
17+
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
18+
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
1519
github.com/cenkalti/backoff/v4 v4.2.1 h1:y4OZtCnogmCPw98Zjyt5a6+QwPLGkiQsYW5oUqylYbM=
1620
github.com/cenkalti/backoff/v4 v4.2.1/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
1721
github.com/containerd/containerd v1.7.27 h1:yFyEyojddO3MIGVER2xJLWoCIn+Up4GaHFquP7hsFII=
@@ -44,6 +48,10 @@ github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4
4448
github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
4549
github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2Wg=
4650
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
51+
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667 h1:BP4M0CvQ4S3TGls2FvczZtj5Re/2ZzkV9VwqPHH/3Bo=
52+
github.com/go-asn1-ber/asn1-ber v1.5.8-0.20250403174932-29230038a667/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
53+
github.com/go-ldap/ldap/v3 v3.4.11 h1:4k0Yxweg+a3OyBLjdYn5OKglv18JNvfDykSoI8bW0gU=
54+
github.com/go-ldap/ldap/v3 v3.4.11/go.mod h1:bY7t0FLK8OAVpp/vV6sSlpz3EQDGcQwc8pF0ujLgKvM=
4755
github.com/go-logr/logr v1.2.2/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A=
4856
github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
4957
github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
@@ -65,6 +73,8 @@ github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0 h1:YBftPWNWd4WwGqtY2yeZL2ef8rH
6573
github.com/grpc-ecosystem/grpc-gateway/v2 v2.16.0/go.mod h1:YN5jB8ie0yfIUg6VvR9Kz84aCaG7AsGZnLjhHbUqwPg=
6674
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
6775
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
76+
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
77+
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
6878
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
6979
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
7080
github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsIM=
@@ -75,6 +85,18 @@ github.com/jackc/pgx/v5 v5.7.3 h1:PO1wNKj/bTAwxSJnO1Z4Ai8j4magtqg2SLNjEDzcXQo=
7585
github.com/jackc/pgx/v5 v5.7.3/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
7686
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
7787
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
88+
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
89+
github.com/jcmturner/aescts/v2 v2.0.0/go.mod h1:AiaICIRyfYg35RUkr8yESTqvSy7csK90qZ5xfvvsoNs=
90+
github.com/jcmturner/dnsutils/v2 v2.0.0 h1:lltnkeZGL0wILNvrNiVCR6Ro5PGU/SeBvVO/8c/iPbo=
91+
github.com/jcmturner/dnsutils/v2 v2.0.0/go.mod h1:b0TnjGOvI/n42bZa+hmXL+kFJZsFT7G4t3HTlQ184QM=
92+
github.com/jcmturner/gofork v1.7.6 h1:QH0l3hzAU1tfT3rZCnW5zXl+orbkNMMRGJfdJjHVETg=
93+
github.com/jcmturner/gofork v1.7.6/go.mod h1:1622LH6i/EZqLloHfE7IeZ0uEJwMSUyQ/nDd82IeqRo=
94+
github.com/jcmturner/goidentity/v6 v6.0.1 h1:VKnZd2oEIMorCTsFBnJWbExfNN7yZr3EhJAxwOkZg6o=
95+
github.com/jcmturner/goidentity/v6 v6.0.1/go.mod h1:X1YW3bgtvwAXju7V3LCIMpY0Gbxyjn/mY9zx4tFonSg=
96+
github.com/jcmturner/gokrb5/v8 v8.4.4 h1:x1Sv4HaTpepFkXbt2IkL29DXRf8sOfZXo8eRKh687T8=
97+
github.com/jcmturner/gokrb5/v8 v8.4.4/go.mod h1:1btQEpgT6k+unzCwX1KdWMEwPPkkgBtP+F6aCACiMrs=
98+
github.com/jcmturner/rpc/v2 v2.0.3 h1:7FXXj8Ti1IaVFpSAziCZWNzbNuZmnvw/i6CqLNdWfZY=
99+
github.com/jcmturner/rpc/v2 v2.0.3/go.mod h1:VUJYCIDm3PVOEHw8sgt091/20OJjskO/YJki3ELg/Hc=
78100
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
79101
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
80102
github.com/klauspost/compress v1.17.4 h1:Ej5ixsIri7BrIjBkRZLTo6ghwrEtHFk7ijlczPW4fZ4=

pkg/ldap/client/client.go

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
package client
2+
3+
import (
4+
// Packages
5+
client "github.com/mutablelogic/go-client"
6+
)
7+
8+
///////////////////////////////////////////////////////////////////////////////
9+
// TYPES
10+
11+
type Client struct {
12+
*client.Client
13+
}
14+
15+
///////////////////////////////////////////////////////////////////////////////
16+
// LIFECYCLE
17+
18+
// Create a new client
19+
func New(url string, opts ...client.ClientOpt) (*Client, error) {
20+
c := new(Client)
21+
if client, err := client.New(append(opts, client.OptEndpoint(url))...); err != nil {
22+
return nil, err
23+
} else {
24+
c.Client = client
25+
}
26+
return c, nil
27+
}

pkg/ldap/client/objects.go

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
package client
2+
3+
import (
4+
"context"
5+
6+
// Packages
7+
client "github.com/mutablelogic/go-client"
8+
schema "github.com/mutablelogic/go-server/pkg/ldap/schema"
9+
)
10+
11+
///////////////////////////////////////////////////////////////////////////////
12+
// PUBLIC METHODS
13+
14+
func (c *Client) ListObjects(ctx context.Context, opts ...Opt) (*schema.ObjectList, error) {
15+
req := client.NewRequest()
16+
17+
// Apply options
18+
opt, err := applyOpts(opts...)
19+
if err != nil {
20+
return nil, err
21+
}
22+
23+
// Perform request
24+
var response schema.ObjectList
25+
if err := c.DoWithContext(ctx, req, &response, client.OptPath("object"), client.OptQuery(opt.Values)); err != nil {
26+
return nil, err
27+
}
28+
29+
// Return the responses
30+
return &response, nil
31+
}

pkg/ldap/client/opts.go

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
package client
2+
3+
import (
4+
"fmt"
5+
"net/url"
6+
7+
// Packages
8+
types "github.com/mutablelogic/go-server/pkg/types"
9+
)
10+
11+
////////////////////////////////////////////////////////////////////////////////
12+
// TYPES
13+
14+
type opt struct {
15+
url.Values
16+
}
17+
18+
// An Option to set on the client
19+
type Opt func(*opt) error
20+
21+
////////////////////////////////////////////////////////////////////////////////
22+
// LIFECYCLE
23+
24+
func applyOpts(opts ...Opt) (*opt, error) {
25+
o := new(opt)
26+
o.Values = make(url.Values)
27+
for _, opt := range opts {
28+
if err := opt(o); err != nil {
29+
return nil, err
30+
}
31+
}
32+
return o, nil
33+
}
34+
35+
////////////////////////////////////////////////////////////////////////////////
36+
// OPTIONS
37+
38+
// Set offset and limit
39+
func WithOffsetLimit(offset uint64, limit *uint64) Opt {
40+
return func(o *opt) error {
41+
if offset > 0 {
42+
o.Set("offset", fmt.Sprint(offset))
43+
}
44+
if limit != nil {
45+
o.Set("limit", fmt.Sprint(*limit))
46+
}
47+
return nil
48+
}
49+
}
50+
51+
// Set LDAP filter
52+
func WithFilter(v *string) Opt {
53+
return OptSet("filter", types.PtrString(v))
54+
}
55+
56+
func OptSet(k, v string) Opt {
57+
return func(o *opt) error {
58+
if v == "" {
59+
o.Del(k)
60+
} else {
61+
o.Set(k, v)
62+
}
63+
return nil
64+
}
65+
}

pkg/ldap/cmd/object.go

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
"fmt"
6+
7+
// Packages
8+
server "github.com/mutablelogic/go-server"
9+
client "github.com/mutablelogic/go-server/pkg/ldap/client"
10+
schema "github.com/mutablelogic/go-server/pkg/ldap/schema"
11+
)
12+
13+
///////////////////////////////////////////////////////////////////////////////
14+
// TYPES
15+
16+
type ObjectCommands struct {
17+
Objects ObjectListCommand `cmd:"" group:"LDAP" help:"List queues"`
18+
}
19+
20+
type ObjectListCommand struct {
21+
schema.ObjectListRequest
22+
}
23+
24+
///////////////////////////////////////////////////////////////////////////////
25+
// PUBLIC METHODS
26+
27+
func (cmd ObjectListCommand) Run(ctx server.Cmd) error {
28+
return run(ctx, func(ctx context.Context, provider *client.Client) error {
29+
queues, err := provider.ListObjects(ctx, client.WithFilter(cmd.Filter), client.WithOffsetLimit(cmd.Offset, cmd.Limit))
30+
if err != nil {
31+
return err
32+
}
33+
34+
// Print queues
35+
fmt.Println(queues)
36+
return nil
37+
})
38+
}

pkg/ldap/cmd/run.go

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
package cmd
2+
3+
import (
4+
"context"
5+
6+
// Packages
7+
server "github.com/mutablelogic/go-server"
8+
client "github.com/mutablelogic/go-server/pkg/ldap/client"
9+
schema "github.com/mutablelogic/go-server/pkg/ldap/schema"
10+
)
11+
12+
///////////////////////////////////////////////////////////////////////////////
13+
// PRIVATE METHODS
14+
15+
func run(ctx server.Cmd, fn func(context.Context, *client.Client) error) error {
16+
// Create a client
17+
provider, err := client.New(ctx.GetEndpoint(schema.APIPrefix).String(), ctx.GetClientOpts()...)
18+
if err != nil {
19+
return err
20+
}
21+
// Run the function
22+
return fn(ctx.Context(), provider)
23+
}

pkg/ldap/config/config.go

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
package config
2+
3+
import (
4+
"context"
5+
"net/url"
6+
7+
// Packages
8+
server "github.com/mutablelogic/go-server"
9+
ldap "github.com/mutablelogic/go-server/pkg/ldap"
10+
handler "github.com/mutablelogic/go-server/pkg/ldap/handler"
11+
schema "github.com/mutablelogic/go-server/pkg/ldap/schema"
12+
)
13+
14+
////////////////////////////////////////////////////////////////////////////////
15+
// TYPES
16+
17+
type Config struct {
18+
Url *url.URL `env:"LDAP_URL" help:"LDAP connection URL"` // Connection URL
19+
Password string `env:"LDAP_PASSWORD" help:"Password"` // Password
20+
BaseDN string `env:"LDAP_BASE_DN" help:"Base DN"` // Base DN
21+
Router server.HTTPRouter `kong:"-"` // HTTP Router
22+
}
23+
24+
var _ server.Plugin = Config{}
25+
26+
////////////////////////////////////////////////////////////////////////////////
27+
// LIFECYCLE
28+
29+
func (c Config) New(ctx context.Context) (server.Task, error) {
30+
// Add options
31+
opts := []ldap.Opt{}
32+
if c.Url != nil {
33+
opts = append(opts, ldap.WithUrl(c.Url.String()))
34+
}
35+
if c.Password != "" {
36+
opts = append(opts, ldap.WithPassword(c.Password))
37+
}
38+
if c.BaseDN != "" {
39+
opts = append(opts, ldap.WithBaseDN(c.BaseDN))
40+
}
41+
42+
// Create a new LDAP manager
43+
manager, err := ldap.NewManager(opts...)
44+
if err != nil {
45+
return nil, err
46+
}
47+
48+
// Register HTTP handlers
49+
if c.Router != nil {
50+
handler.Register(ctx, c.Router, manager)
51+
}
52+
53+
// Return the task
54+
return NewTask(manager)
55+
}
56+
57+
////////////////////////////////////////////////////////////////////////////////
58+
// MODULE
59+
60+
func (c Config) Name() string {
61+
return schema.SchemaName
62+
}
63+
64+
func (c Config) Description() string {
65+
return "LDAP manager"
66+
}

0 commit comments

Comments
 (0)