Skip to content

Commit

Permalink
Merge pull request #36 from ConductorOne/ggreer/fix-attributes
Browse files Browse the repository at this point in the history
Add non-posix users. Add option to disable fetching operational attributes.
  • Loading branch information
ggreer authored May 15, 2024
2 parents 1f4552f + 4812771 commit d3b0e83
Show file tree
Hide file tree
Showing 7 changed files with 58 additions and 26 deletions.
3 changes: 0 additions & 3 deletions .golangci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,9 +50,6 @@ linters-settings:
tenv:
all: true

varcheck:
exported-fields: false # this appears to improperly detect exported variables as unused when they are used from a package with the same name


linters:
disable-all: true
Expand Down
11 changes: 7 additions & 4 deletions cmd/baton-ldap/config.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,10 +13,11 @@ import (
type config struct {
cli.BaseConfig `mapstructure:",squash"` // Puts the base config options in the same place as the connector options

Domain string `mapstructure:"domain"`
BaseDN string `mapstructure:"base-dn"`
Password string `mapstructure:"password"`
UserDN string `mapstructure:"user-dn"`
Domain string `mapstructure:"domain"`
BaseDN string `mapstructure:"base-dn"`
Password string `mapstructure:"password"`
UserDN string `mapstructure:"user-dn"`
DisableOperationalAttrs bool `mapstructure:"disable-operational-attrs"`
}

// validateConfig is run after the configuration is loaded, and should return an error if it isn't valid.
Expand Down Expand Up @@ -48,4 +49,6 @@ func cmdFlags(cmd *cobra.Command) {
cmd.PersistentFlags().String("base-dn", "", "The base DN to search from. Example: \"DC=baton,DC=example,DC=com\" ($BATON_BASE_DN)")
cmd.PersistentFlags().String("password", "", "The password to bind to the LDAP server. ($BATON_PASSWORD)")
cmd.PersistentFlags().String("user-dn", "", "The user DN to bind to the LDAP server. ($BATON_USER_DN)")
cmd.PersistentFlags().Bool("disable-operational-attrs", false,
"Disable fetching operational attributes. Some LDAP servers don't support these. If disabled, created_at and last login info will not be fetched. ($BATON_DISABLE_OPERATIONAL_ATTRS)")
}
2 changes: 1 addition & 1 deletion cmd/baton-ldap/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ func main() {
func getConnector(ctx context.Context, cfg *config) (types.ConnectorServer, error) {
l := ctxzap.Extract(ctx)

ldapConnector, err := connector.New(ctx, cfg.Domain, cfg.BaseDN, cfg.Password, cfg.UserDN)
ldapConnector, err := connector.New(ctx, cfg.Domain, cfg.BaseDN, cfg.Password, cfg.UserDN, cfg.DisableOperationalAttrs)
if err != nil {
l.Error("error creating connector", zap.Error(err))
return nil, err
Expand Down
10 changes: 6 additions & 4 deletions pkg/connector/connector.go
Original file line number Diff line number Diff line change
Expand Up @@ -36,12 +36,13 @@ var (
)

type LDAP struct {
client *ldap.Client
client *ldap.Client
disableOperationalAttrs bool
}

func (l *LDAP) ResourceSyncers(ctx context.Context) []connectorbuilder.ResourceSyncer {
return []connectorbuilder.ResourceSyncer{
userBuilder(l.client),
userBuilder(l.client, l.disableOperationalAttrs),
groupBuilder(l.client),
roleBuilder(l.client),
}
Expand Down Expand Up @@ -72,7 +73,7 @@ func (l *LDAP) Validate(ctx context.Context) (annotations.Annotations, error) {
}

// New returns the LDAP connector.
func New(ctx context.Context, domain string, baseDN string, password string, userDN string) (*LDAP, error) {
func New(ctx context.Context, domain string, baseDN string, password string, userDN string, disableOperationalAttrs bool) (*LDAP, error) {
conn, err := ldap.TestConnection(domain)
if err != nil {
return nil, err
Expand All @@ -85,6 +86,7 @@ func New(ctx context.Context, domain string, baseDN string, password string, use
}

return &LDAP{
client: ldapClient,
client: ldapClient,
disableOperationalAttrs: disableOperationalAttrs,
}, nil
}
21 changes: 14 additions & 7 deletions pkg/connector/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,12 @@ const (
attrUserAccountControl = "userAccountControl"
)

var userAttrs = []string{"*", "+"}
var allAttrs = []string{"*", "+"}

type userResourceType struct {
resourceType *v2.ResourceType
client *ldap.Client
resourceType *v2.ResourceType
client *ldap.Client
disableOperationalAttrs bool
}

func (u *userResourceType) ResourceType(_ context.Context) *v2.ResourceType {
Expand Down Expand Up @@ -146,10 +147,15 @@ func (u *userResourceType) List(ctx context.Context, _ *v2.ResourceId, pt *pagin
return nil, "", nil, err
}

attrs := allAttrs
if u.disableOperationalAttrs {
attrs = []string{"*"}
}

userEntries, nextPage, err := u.client.LdapSearch(
ctx,
userFilter,
userAttrs,
attrs,
page,
uint32(ResourcesPageSize),
"",
Expand Down Expand Up @@ -186,9 +192,10 @@ func (u *userResourceType) Grants(ctx context.Context, resource *v2.Resource, to
return nil, "", nil, nil
}

func userBuilder(client *ldap.Client) *userResourceType {
func userBuilder(client *ldap.Client, disableOperationalAttrs bool) *userResourceType {
return &userResourceType{
resourceType: resourceTypeUser,
client: client,
resourceType: resourceTypeUser,
client: client,
disableOperationalAttrs: disableOperationalAttrs,
}
}
2 changes: 2 additions & 0 deletions pkg/ldap/client.go
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,8 @@ func (c *Client) CreateMemberEntry(ctx context.Context, memberId string) (string
func (c *Client) LdapModify(ctx context.Context, modifyRequest *ldap.ModifyRequest) error {
l := ctxzap.Extract(ctx)

l.Debug("modifying ldap entry", zap.String("DN", modifyRequest.DN), zap.Any("changes", modifyRequest.Changes))

err := c.getConnection(ctx, true, func(client *ldapConn) error {
return client.conn.Modify(modifyRequest)
})
Expand Down
35 changes: 28 additions & 7 deletions scripts/ldif.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ gidNumber: ${groupId}

for (let userId = 0; userId < userCount; userId++) {
const userIdStr = ("00000" + userId).slice(-5);
groupStr += `memberuid: testuser${userIdStr}
groupStr += `memberUid: testuser${userIdStr}
`;
}

Expand All @@ -85,22 +85,43 @@ owner: cn=testuser00000,dc=example,dc=org
}

// Users
for (let userId = 0; userId < 5000; userId++) {
const userIdStr = ("00000" + userId).slice(-5);
write(`dn: cn=testuser${userIdStr},dc=example,dc=org
for (let userId = 0; userId < userCount; userId++) {
const userIdStr = ("00000" + userId).slice(-5);
const email = `testuser${userIdStr}@example.com`
write(`dn: cn=testuser${userIdStr},dc=example,dc=org
objectClass: inetOrgPerson
objectClass: posixAccount
objectClass: shadowAccount
telephoneNumber: +1509555${userIdStr}
uid: testuser${userIdStr}
sn: testuser${userIdStr}
givenName: test
cn: testuser${userIdStr}
displayName: test
givenName: test ${userIdStr}
cn: ${email}
displayName: test ${userIdStr}
uidNumber: ${(10000 + userId).toString()}
gidNumber: 500
gecos: Test User ${userIdStr}
loginShell: /bin/bash
homeDirectory: /home/testuser${userIdStr}
title: Test*User ${userIdStr}
`);
}

// Non-posix users
for (let userId = 0; userId < userCount; userId++) {
const userIdStr = ("00000" + userId).slice(-5);
const email = `othertestuser${userIdStr}@example.com`
write(`dn: cn=${email},dc=example,dc=org
objectClass: inetOrgPerson
objectClass: top
telephoneNumber: +1509555${userIdStr}
sn: othertestuser${userIdStr}
uid: othertestuser${userIdStr}
givenName: test ${userIdStr}
cn: ${email}
displayName: other test ${userIdStr}
title: Test*User ${userIdStr}
`);
}

0 comments on commit d3b0e83

Please sign in to comment.