Bump reva to latest main

to get https://github.com/opencloud-eu/reva/pull/339
This commit is contained in:
Ralf Haferkamp
2025-09-09 15:10:28 +02:00
committed by Ralf Haferkamp
parent a5e0c1ec4b
commit 65228f3188
27 changed files with 388 additions and 148 deletions
+2 -9
View File
@@ -1,7 +1,7 @@
package backoff
import (
"math/rand"
"math/rand/v2"
"time"
)
@@ -28,13 +28,7 @@ multiplied by the exponential, that is, between 2 and 6 seconds.
Note: MaxInterval caps the RetryInterval and not the randomized interval.
If the time elapsed since an ExponentialBackOff instance is created goes past the
MaxElapsedTime, then the method NextBackOff() starts returning backoff.Stop.
The elapsed time can be reset by calling Reset().
Example: Given the following default arguments, for 10 tries the sequence will be,
and assuming we go over the MaxElapsedTime on the 10th try:
Example: Given the following default arguments, for 9 tries the sequence will be:
Request # RetryInterval (seconds) Randomized Interval (seconds)
@@ -47,7 +41,6 @@ and assuming we go over the MaxElapsedTime on the 10th try:
7 5.692 [2.846, 8.538]
8 8.538 [4.269, 12.807]
9 12.807 [6.403, 19.210]
10 19.210 backoff.Stop
Note: Implementation is not thread-safe.
*/
+2 -2
View File
@@ -47,7 +47,7 @@ func WithNotify(n Notify) RetryOption {
}
}
// WithMaxTries limits the number of retry attempts.
// WithMaxTries limits the number of all attempts.
func WithMaxTries(n uint) RetryOption {
return func(args *retryOptions) {
args.MaxTries = n
@@ -97,7 +97,7 @@ func Retry[T any](ctx context.Context, operation Operation[T], opts ...RetryOpti
// Handle permanent errors without retrying.
var permanent *PermanentError
if errors.As(err, &permanent) {
return res, err
return res, permanent.Unwrap()
}
// Stop retrying if context is cancelled.
@@ -136,6 +136,11 @@ func (s *service) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*use
return res, nil
}
// Only request users from the same tenant as the current user
if currentUser, ok := revactx.ContextGetUser(ctx); ok {
req.UserId.TenantId = currentUser.GetId().GetTenantId()
}
user, err := s.usermgr.GetUser(ctx, req.UserId, req.SkipFetchingUserGroups)
if err != nil {
res := &userpb.GetUserResponse{}
@@ -155,7 +160,11 @@ func (s *service) GetUser(ctx context.Context, req *userpb.GetUserRequest) (*use
}
func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaimRequest) (*userpb.GetUserByClaimResponse, error) {
user, err := s.usermgr.GetUserByClaim(ctx, req.Claim, req.Value, req.SkipFetchingUserGroups)
tenantID := ""
if currentUser, ok := revactx.ContextGetUser(ctx); ok {
tenantID = currentUser.GetId().GetTenantId()
}
user, err := s.usermgr.GetUserByClaim(ctx, req.Claim, req.Value, tenantID, req.SkipFetchingUserGroups)
if err != nil {
res := &userpb.GetUserByClaimResponse{}
if _, ok := err.(errtypes.NotFound); ok {
@@ -176,7 +185,7 @@ func (s *service) GetUserByClaim(ctx context.Context, req *userpb.GetUserByClaim
func (s *service) FindUsers(ctx context.Context, req *userpb.FindUsersRequest) (*userpb.FindUsersResponse, error) {
currentUser := revactx.ContextMustGetUser(ctx)
users, err := s.usermgr.FindUsers(ctx, req.Filter, currentUser.Id.GetTenantId(), req.SkipFetchingUserGroups)
users, err := s.usermgr.FindUsers(ctx, req.Filter, currentUser.GetId().GetTenantId(), req.SkipFetchingUserGroups)
if err != nil {
res := &userpb.FindUsersResponse{
Status: status.NewInternal(ctx, "error finding users"),
+1 -1
View File
@@ -108,7 +108,7 @@ func (am *mgr) Authenticate(ctx context.Context, clientID, clientSecret string)
filter := am.getLoginFilter(clientID)
userEntry, err := am.c.LDAPIdentity.GetLDAPUserByFilter(log, am.ldapClient, filter)
userEntry, err := am.c.LDAPIdentity.GetLDAPUserByFilter(ctx, am.ldapClient, filter)
if err != nil {
return nil, nil, err
+7 -1
View File
@@ -224,6 +224,9 @@ func (m *manager) parseAndCacheUser(ctx context.Context, userData map[string]int
}
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if uid.GetTenantId() != "" {
return nil, errtypes.NotSupported("tenant filter not supported in rest user manager")
}
u, err := m.fetchCachedUserDetails(uid)
if err != nil {
return nil, err
@@ -240,7 +243,10 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return u, nil
}
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
if tenantID != "" {
return nil, errtypes.NotSupported("tenant filter not supported in rest user manager")
}
u, err := m.fetchCachedUserByParam(claim, value)
if err != nil {
return nil, err
+48 -8
View File
@@ -35,6 +35,7 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/utils"
ldapIdentity "github.com/opencloud-eu/reva/v2/pkg/utils/ldap"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"
)
func init() {
@@ -54,6 +55,8 @@ type config struct {
Nobody int64 `mapstructure:"nobody"`
}
const tracerName = "pkg/group/manager/ldap"
func parseConfig(m map[string]interface{}) (*config, error) {
c := config{
LDAPIdentity: ldapIdentity.New(),
@@ -100,12 +103,20 @@ func (m *manager) Configure(ml map[string]interface{}) error {
// GetGroup implements the group.Manager interface. Looks up a group by Id and return the group
func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchingMembers bool) (*grouppb.Group, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetGroup")
defer span.End()
span.SetAttributes(
attribute.Stringer("group_id", gid),
attribute.Bool("skip_fetching_members", skipFetchingMembers),
)
log := appctx.GetLogger(ctx)
if gid.Idp != "" && gid.Idp != m.c.Idp {
return nil, errtypes.NotFound("idp mismatch")
}
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByID(log, m.ldapClient, gid.OpaqueId)
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByID(ctx, m.ldapClient, gid.OpaqueId)
if err != nil {
return nil, err
}
@@ -121,7 +132,7 @@ func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchi
return g, nil
}
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(log, m.ldapClient, groupEntry)
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(ctx, m.ldapClient, groupEntry)
if err != nil {
return nil, err
}
@@ -144,8 +155,17 @@ func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId, skipFetchi
// GetGroupByClaim implements the group.Manager interface. Looks up a group by
// claim ('group_name', 'group_id', 'display_name') and returns the group.
func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skipFetchingMembers bool) (*grouppb.Group, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetGroupByClaim")
defer span.End()
span.SetAttributes(
attribute.String("claim", claim),
attribute.String("value", value),
attribute.Bool("skip_fetching_members", skipFetchingMembers),
)
log := appctx.GetLogger(ctx)
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByAttribute(log, m.ldapClient, claim, value)
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByAttribute(ctx, m.ldapClient, claim, value)
if err != nil {
log.Debug().Err(err).Msg("GetGroupByClaim")
return nil, err
@@ -162,7 +182,7 @@ func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skip
return g, nil
}
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(log, m.ldapClient, groupEntry)
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(ctx, m.ldapClient, groupEntry)
if err != nil {
return nil, err
}
@@ -187,8 +207,15 @@ func (m *manager) GetGroupByClaim(ctx context.Context, claim, value string, skip
// 'display_name', 'group_id') and returns the groups. FindGroups does NOT expand the
// members of the Groups.
func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMembers bool) ([]*grouppb.Group, error) {
log := appctx.GetLogger(ctx)
entries, err := m.c.LDAPIdentity.GetLDAPGroups(log, m.ldapClient, query)
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "FindGroups")
defer span.End()
span.SetAttributes(
attribute.String("query", query),
attribute.Bool("skip_fetching_members", skipFetchingMembers),
)
entries, err := m.c.LDAPIdentity.GetLDAPGroups(ctx, m.ldapClient, query)
if err != nil {
return nil, err
}
@@ -210,19 +237,25 @@ func (m *manager) FindGroups(ctx context.Context, query string, skipFetchingMemb
// GetMembers implements the group.Manager interface. It returns all the userids of the members
// of the group identified by the supplied id.
func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*userpb.UserId, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetMembers")
defer span.End()
span.SetAttributes(
attribute.Stringer("group_id", gid),
)
log := appctx.GetLogger(ctx)
if gid.Idp != "" && gid.Idp != m.c.Idp {
return nil, errtypes.NotFound("idp mismatch")
}
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByID(log, m.ldapClient, gid.OpaqueId)
groupEntry, err := m.c.LDAPIdentity.GetLDAPGroupByID(ctx, m.ldapClient, gid.OpaqueId)
if err != nil {
return nil, err
}
log.Debug().Interface("entry", groupEntry).Msg("entries")
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(log, m.ldapClient, groupEntry)
members, err := m.c.LDAPIdentity.GetLDAPGroupMembers(ctx, m.ldapClient, groupEntry)
if err != nil {
return nil, err
}
@@ -243,6 +276,13 @@ func (m *manager) GetMembers(ctx context.Context, gid *grouppb.GroupId) ([]*user
// HasMember implements the group.Member interface. Checks whether the supplied userid is a member
// of the supplied groupid.
func (m *manager) HasMember(ctx context.Context, gid *grouppb.GroupId, uid *userpb.UserId) (bool, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "HasMember")
defer span.End()
span.SetAttributes(
attribute.Stringer("group_id", gid),
attribute.Stringer("user_id", uid),
)
// It might be possible to do a somewhat more clever LDAP search here. (First lookup the user and then
// search for (&(objectclass=<groupoc>)(<groupid>=gid)(member=<username/userdn>)
// The GetMembers call used below can be quiet ineffecient for large groups
+3 -3
View File
@@ -57,7 +57,7 @@ func (m *manager) Configure(ml map[string]interface{}) error {
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if user, ok := m.catalog[uid.OpaqueId]; ok {
if uid.Idp == "" || user.Id.Idp == uid.Idp {
if user.GetId().GetTenantId() == uid.GetTenantId() && (uid.Idp == "" || user.Id.Idp == uid.Idp) {
u := proto.Clone(user).(*userpb.User)
if skipFetchingGroups {
u.Groups = nil
@@ -68,9 +68,9 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return nil, errtypes.NotFound(uid.OpaqueId)
}
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
for _, u := range m.catalog {
if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim {
if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim && tenantID == u.Id.TenantId {
user := proto.Clone(u).(*userpb.User)
if skipFetchingGroups {
user.Groups = nil
+3 -3
View File
@@ -97,7 +97,7 @@ func (m *manager) Configure(ml map[string]interface{}) error {
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
for _, u := range m.users {
if (u.Id.GetOpaqueId() == uid.OpaqueId || u.Username == uid.OpaqueId) && (uid.Idp == "" || uid.Idp == u.Id.GetIdp()) {
if (u.Id.GetOpaqueId() == uid.OpaqueId || u.Username == uid.OpaqueId) && (uid.Idp == "" || uid.Idp == u.Id.GetIdp()) && (uid.GetTenantId() == u.Id.GetTenantId()) {
user := proto.Clone(u).(*userpb.User)
if skipFetchingGroups {
user.Groups = nil
@@ -108,9 +108,9 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return nil, errtypes.NotFound(uid.OpaqueId)
}
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
for _, u := range m.users {
if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim {
if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim && tenantID == u.Id.TenantId {
user := proto.Clone(u).(*userpb.User)
if skipFetchingGroups {
user.Groups = nil
+36 -12
View File
@@ -34,12 +34,15 @@ import (
"github.com/opencloud-eu/reva/v2/pkg/utils"
ldapIdentity "github.com/opencloud-eu/reva/v2/pkg/utils/ldap"
"github.com/pkg/errors"
"go.opentelemetry.io/otel/attribute"
)
func init() {
registry.Register("ldap", New)
}
const tracerName = "pkg/user/manager/ldap"
type manager struct {
c *config
ldapClient ldap.Client
@@ -96,15 +99,22 @@ func (m *manager) Configure(ml map[string]interface{}) error {
// GetUser implements the user.Manager interface. Looks up a user by Id and return the user
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
log := appctx.GetLogger(ctx)
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetUser")
defer span.End()
span.SetAttributes(
attribute.Stringer("parameter.userid", uid),
attribute.Bool("parameter.skipFetchingGroups", skipFetchingGroups),
)
log := appctx.GetLogger(ctx)
log.Debug().Interface("id", uid).Msg("GetUser")
// If the Idp value in the uid does not match our config, we can't answer this request
if uid.Idp != "" && uid.Idp != m.c.Idp {
return nil, errtypes.NotFound("idp mismatch")
}
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByID(log, m.ldapClient, uid.OpaqueId)
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByID(ctx, m.ldapClient, uid)
if err != nil {
return nil, err
}
@@ -120,7 +130,7 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return u, nil
}
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(log, m.ldapClient, userEntry)
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(ctx, m.ldapClient, userEntry)
if err != nil {
return nil, err
}
@@ -131,11 +141,18 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
// GetUserByClaim implements the user.Manager interface. Looks up a user by
// claim ('mail', 'username', 'userid') and returns the user.
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
log := appctx.GetLogger(ctx)
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetUserByClaim")
defer span.End()
span.SetAttributes(
attribute.String("parameter.claim", claim),
attribute.String("paramter.value", value),
attribute.Bool("parameter.skipFetchingGroups", skipFetchingGroups),
)
log.Debug().Str("claim", claim).Str("value", value).Msg("GetUserByClaim")
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByAttribute(log, m.ldapClient, claim, value)
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByAttribute(ctx, m.ldapClient, claim, value, tenantID)
if err != nil {
log.Debug().Err(err).Msg("GetUserByClaim")
return nil, err
@@ -148,7 +165,7 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipF
return nil, err
}
if m.c.LDAPIdentity.IsLDAPUserInDisabledGroup(log, m.ldapClient, userEntry) {
if m.c.LDAPIdentity.IsLDAPUserInDisabledGroup(ctx, m.ldapClient, userEntry) {
return nil, errtypes.NotFound("user is locally disabled")
}
@@ -156,7 +173,7 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipF
return u, nil
}
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(log, m.ldapClient, userEntry)
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(ctx, m.ldapClient, userEntry)
if err != nil {
return nil, err
}
@@ -169,8 +186,15 @@ func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipF
// FindUser implements the user.Manager interface. Searches for users using a prefix-substring search on
// the user attributes ('mail', 'username', 'displayname', 'userid') and returns the users.
func (m *manager) FindUsers(ctx context.Context, query, tenantID string, skipFetchingGroups bool) ([]*userpb.User, error) {
log := appctx.GetLogger(ctx)
entries, err := m.c.LDAPIdentity.GetLDAPUsers(log, m.ldapClient, query, tenantID)
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "FindUsers")
defer span.End()
span.SetAttributes(
attribute.String("parameter.query", query),
attribute.String("parameter.tenantID", tenantID),
attribute.Bool("parameter.skipFetchingGroups", skipFetchingGroups),
)
entries, err := m.c.LDAPIdentity.GetLDAPUsers(ctx, m.ldapClient, query, tenantID)
if err != nil {
return nil, err
}
@@ -183,7 +207,7 @@ func (m *manager) FindUsers(ctx context.Context, query, tenantID string, skipFet
}
if !skipFetchingGroups {
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(log, m.ldapClient, entry)
groups, err := m.c.LDAPIdentity.GetLDAPUserGroups(ctx, m.ldapClient, entry)
if err != nil {
return nil, err
}
@@ -204,12 +228,12 @@ func (m *manager) GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]stri
log.Debug().Str("useridp", uid.Idp).Str("configured idp", m.c.Idp).Msg("IDP mismatch")
return nil, errtypes.NotFound("idp mismatch")
}
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByID(log, m.ldapClient, uid.OpaqueId)
userEntry, err := m.c.LDAPIdentity.GetLDAPUserByID(ctx, m.ldapClient, uid)
if err != nil {
log.Debug().Err(err).Interface("userid", uid).Msg("Failed to lookup user")
return []string{}, err
}
return m.c.LDAPIdentity.GetLDAPUserGroups(log, m.ldapClient, userEntry)
return m.c.LDAPIdentity.GetLDAPUserGroups(ctx, m.ldapClient, userEntry)
}
func (m *manager) ldapEntryToUser(entry *ldap.Entry) (*userpb.User, error) {
+8 -1
View File
@@ -84,6 +84,9 @@ func (m *manager) Configure(ml map[string]interface{}) error {
}
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if uid.GetTenantId() != "" {
return nil, errtypes.NotSupported("tenant filter not supported in memory user manager")
}
if user, ok := m.catalog[uid.OpaqueId]; ok {
if uid.Idp == "" || user.ID.Idp == uid.Idp {
u := *user
@@ -106,7 +109,11 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return nil, errtypes.NotFound(uid.OpaqueId)
}
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
if tenantID != "" {
return nil, errtypes.NotSupported("tenant filter not supported in memory user manager")
}
for _, u := range m.catalog {
if userClaim, err := extractClaim(u, claim); err == nil && value == userClaim {
user := &userpb.User{
@@ -151,6 +151,9 @@ func (um *Manager) Configure(ml map[string]interface{}) error {
// GetUser method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35
func (um *Manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if uid.GetTenantId() != "" {
return nil, errtypes.NotSupported("tenant filter not supported in nextcloud user manager")
}
bodyStr, _ := json.Marshal(uid)
_, respBody, err := um.do(ctx, Action{"GetUser", string(bodyStr)}, "unauthenticated")
if err != nil {
@@ -165,7 +168,10 @@ func (um *Manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetching
}
// GetUserByClaim method as defined in https://github.com/cs3org/reva/blob/v1.13.0/pkg/user/user.go#L29-L35
func (um *Manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (um *Manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
if tenantID != "" {
return nil, errtypes.NotSupported("tenant filter not supported in nextcloud user manager")
}
type paramsObj struct {
Claim string `json:"claim"`
Value string `json:"value"`
@@ -103,6 +103,9 @@ func parseConfig(m map[string]interface{}) (*config, error) {
}
func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if uid.GetTenantId() != "" {
return nil, errtypes.NotSupported("tenant filter not supported in opencloudsql user manager")
}
// search via the user_id
a, err := m.db.GetAccountByClaim(ctx, "userid", uid.OpaqueId)
if err == sql.ErrNoRows {
@@ -111,7 +114,11 @@ func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingG
return m.convertToCS3User(ctx, a, skipFetchingGroups)
}
func (m *manager) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *manager) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
if tenantID != "" {
return nil, errtypes.NotSupported("tenant filter not supported in opencloudsql user manager")
}
a, err := m.db.GetAccountByClaim(ctx, claim, value)
if err == sql.ErrNoRows {
return nil, errtypes.NotFound(claim + "=" + value)
+9 -2
View File
@@ -89,6 +89,9 @@ type GetUserReply struct {
// GetUser RPCClient GetUser method
func (m *RPCClient) GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error) {
if uid.GetTenantId() != "" {
return nil, errtypes.NotSupported("tenant filter not supported in rpc_user user manager")
}
ctxVal := appctx.GetKeyValuesFromCtx(ctx)
args := GetUserArg{Ctx: ctxVal, UID: uid, SkipFetchingGroups: skipFetchingGroups}
resp := GetUserReply{}
@@ -114,7 +117,11 @@ type GetUserByClaimReply struct {
}
// GetUserByClaim RPCClient GetUserByClaim method
func (m *RPCClient) GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error) {
func (m *RPCClient) GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error) {
if tenantID != "" {
return nil, errtypes.NotSupported("tenant filter not supported in rpc_user user manager")
}
ctxVal := appctx.GetKeyValuesFromCtx(ctx)
args := GetUserByClaimArg{Ctx: ctxVal, Claim: claim, Value: value, SkipFetchingGroups: skipFetchingGroups}
resp := GetUserByClaimReply{}
@@ -200,7 +207,7 @@ func (m *RPCServer) GetUser(args GetUserArg, resp *GetUserReply) error {
// GetUserByClaim RPCServer GetUserByClaim method
func (m *RPCServer) GetUserByClaim(args GetUserByClaimArg, resp *GetUserByClaimReply) error {
ctx := appctx.PutKeyValuesToCtx(args.Ctx)
resp.User, resp.Err = m.Impl.GetUserByClaim(ctx, args.Claim, args.Value, args.SkipFetchingGroups)
resp.User, resp.Err = m.Impl.GetUserByClaim(ctx, args.Claim, args.Value, "", args.SkipFetchingGroups)
return nil
}
+1 -1
View File
@@ -33,7 +33,7 @@ type Manager interface {
// and might involve computational overhead.
GetUser(ctx context.Context, uid *userpb.UserId, skipFetchingGroups bool) (*userpb.User, error)
// GetUserByClaim returns the user identified by a specific value for a given claim.
GetUserByClaim(ctx context.Context, claim, value string, skipFetchingGroups bool) (*userpb.User, error)
GetUserByClaim(ctx context.Context, claim, value, tenantID string, skipFetchingGroups bool) (*userpb.User, error)
// GetUserGroups returns the groups a user identified by a uid belongs to.
GetUserGroups(ctx context.Context, uid *userpb.UserId) ([]string, error)
// FindUsers returns all the user objects which match a query parameter.
+144 -66
View File
@@ -19,15 +19,20 @@
package ldap
import (
"context"
"fmt"
"strings"
identityUser "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1"
"github.com/go-ldap/ldap/v3"
"github.com/google/uuid"
"github.com/opencloud-eu/reva/v2/pkg/appctx"
"github.com/opencloud-eu/reva/v2/pkg/errtypes"
"github.com/pkg/errors"
"github.com/rs/zerolog"
"github.com/rs/zerolog/log"
"go.opentelemetry.io/otel/attribute"
"go.opentelemetry.io/otel/codes"
"go.opentelemetry.io/otel/trace"
)
// Identity provides methods to query users and groups from an LDAP server
@@ -36,6 +41,8 @@ type Identity struct {
Group groupConfig `mapstructure:",squash"`
}
const tracerName = "pkg/utils/ldap"
type userConfig struct {
BaseDN string `mapstructure:"user_base_dn"`
Scope string `mapstructure:"user_search_scope"`
@@ -178,45 +185,40 @@ func (i *Identity) Setup() error {
// GetLDAPUserByID looks up a user by the supplied Id. Returns the corresponding
// ldap.Entry
func (i *Identity) GetLDAPUserByID(log *zerolog.Logger, lc ldap.Client, id string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPUserByID(ctx context.Context, lc ldap.Client, id *identityUser.UserId) (*ldap.Entry, error) {
var filter string
var err error
if filter, err = i.getUserFilter(id); err != nil {
return nil, err
}
return i.GetLDAPUserByFilter(log, lc, filter)
return i.GetLDAPUserByFilter(ctx, lc, filter)
}
// GetLDAPUserByAttribute looks up a single user by attribute (can be "mail",
// "uid", "gid", "username" or "userid"). Returns the corresponding ldap.Entry
func (i *Identity) GetLDAPUserByAttribute(log *zerolog.Logger, lc ldap.Client, attribute, value string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPUserByAttribute(ctx context.Context, lc ldap.Client, attribute, value, tenantID string) (*ldap.Entry, error) {
var filter string
var err error
if filter, err = i.getUserAttributeFilter(attribute, value); err != nil {
if filter, err = i.getUserAttributeFilter(attribute, value, tenantID); err != nil {
return nil, err
}
return i.GetLDAPUserByFilter(log, lc, filter)
return i.GetLDAPUserByFilter(ctx, lc, filter)
}
// GetLDAPUserByFilter looks up a single user by the supplied LDAP filter
// returns the corresponding ldap.Entry
func (i *Identity) GetLDAPUserByFilter(log *zerolog.Logger, lc ldap.Client, filter string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPUserByFilter(ctx context.Context, lc ldap.Client, filter string) (*ldap.Entry, error) {
log := appctx.GetLogger(ctx)
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPUserByFilter")
defer span.End()
searchRequest := ldap.NewSearchRequest(
i.User.BaseDN, i.User.scopeVal, ldap.NeverDerefAliases, 1, 0, false,
filter,
[]string{
i.User.Schema.DisplayName,
i.User.Schema.ID,
i.User.Schema.TenantID,
i.User.Schema.Mail,
i.User.Schema.Username,
i.User.Schema.UIDNumber,
i.User.Schema.GIDNumber,
i.User.EnabledProperty,
i.User.UserTypeProperty,
},
i.getUserLDAPAttrTypes(),
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
log.Debug().Str("backend", "ldap").Str("basedn", i.User.BaseDN).Str("filter", filter).Int("scope", i.User.scopeVal).Msg("LDAP Search")
res, err := lc.Search(searchRequest)
if err != nil {
@@ -227,18 +229,25 @@ func (i *Identity) GetLDAPUserByFilter(log *zerolog.Logger, lc ldap.Client, filt
errmsg = fmt.Sprintf("too many results searching for user '%s'", filter)
}
}
span.SetAttributes(attribute.String("ldap.error", errmsg))
span.SetStatus(codes.Error, errmsg)
return nil, errtypes.NotFound(errmsg)
}
if len(res.Entries) == 0 {
return nil, errtypes.NotFound(filter)
}
span.SetStatus(codes.Ok, "")
return res.Entries[0], nil
}
// GetLDAPUserByDN looks up a single user by the supplied LDAP DN
// returns the corresponding ldap.Entry
func (i *Identity) GetLDAPUserByDN(log *zerolog.Logger, lc ldap.Client, dn string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPUserByDN(ctx context.Context, lc ldap.Client, dn string) (*ldap.Entry, error) {
log := appctx.GetLogger(ctx)
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPUserByDN")
defer span.End()
filter := fmt.Sprintf("(objectclass=%s)", i.User.Objectclass)
if i.User.Filter != "" {
filter = fmt.Sprintf("(&%s%s)", i.User.Filter, filter)
@@ -246,23 +255,19 @@ func (i *Identity) GetLDAPUserByDN(log *zerolog.Logger, lc ldap.Client, dn strin
searchRequest := ldap.NewSearchRequest(
dn, i.User.scopeVal, ldap.NeverDerefAliases, 1, 0, false,
filter,
[]string{
i.User.Schema.DisplayName,
i.User.Schema.ID,
i.User.Schema.Mail,
i.User.Schema.Username,
i.User.Schema.UIDNumber,
i.User.Schema.GIDNumber,
i.User.EnabledProperty,
},
i.getUserLDAPAttrTypes(),
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
log.Debug().Str("backend", "ldap").Str("basedn", dn).Str("filter", filter).Int("scope", i.User.scopeVal).Msg("LDAP Search")
res, err := lc.Search(searchRequest)
if err != nil {
log.Debug().Str("backend", "ldap").Err(err).Str("dn", dn).Msg("Error looking up user by DN")
span.SetAttributes(attribute.String("ldap.error", err.Error()))
span.SetStatus(codes.Error, "")
return nil, errtypes.NotFound(dn)
}
span.SetStatus(codes.Ok, "")
if len(res.Entries) == 0 {
return nil, errtypes.NotFound(dn)
}
@@ -272,36 +277,42 @@ func (i *Identity) GetLDAPUserByDN(log *zerolog.Logger, lc ldap.Client, dn strin
// GetLDAPUsers searches for users using a prefix-substring match on the user
// attributes. Returns a slice of matching ldap.Entries
func (i *Identity) GetLDAPUsers(log *zerolog.Logger, lc ldap.Client, query, tenantID string) ([]*ldap.Entry, error) {
func (i *Identity) GetLDAPUsers(ctx context.Context, lc ldap.Client, query, tenantID string) ([]*ldap.Entry, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPUsers")
defer span.End()
log := appctx.GetLogger(ctx)
filter := i.getUserFindFilter(query, tenantID)
searchRequest := ldap.NewSearchRequest(
i.User.BaseDN,
i.User.scopeVal, ldap.NeverDerefAliases, 0, 0, false,
filter,
[]string{
i.User.Schema.ID,
i.User.Schema.Username,
i.User.Schema.Mail,
i.User.Schema.DisplayName,
i.User.Schema.UIDNumber,
i.User.Schema.GIDNumber,
i.User.EnabledProperty,
i.User.UserTypeProperty,
},
i.getUserLDAPAttrTypes(),
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
log.Debug().Str("backend", "ldap").Str("basedn", i.User.BaseDN).Str("filter", filter).Int("scope", i.User.scopeVal).Msg("LDAP Search")
sr, err := lc.Search(searchRequest)
if err != nil {
log.Debug().Str("backend", "ldap").Err(err).Str("filter", filter).Msg("Error searching users")
span.SetAttributes(attribute.String("ldap.error", err.Error()))
span.SetStatus(codes.Error, "")
return nil, errtypes.NotFound(query)
}
span.SetAttributes(attribute.Int("ldap.result_count", len(sr.Entries)))
span.SetStatus(codes.Ok, "")
return sr.Entries, nil
}
// IsLDAPUserInDisabledGroup checkes if the user is in the disabled group.
func (i *Identity) IsLDAPUserInDisabledGroup(log *zerolog.Logger, lc ldap.Client, userEntry *ldap.Entry) bool {
func (i *Identity) IsLDAPUserInDisabledGroup(ctx context.Context, lc ldap.Client, userEntry *ldap.Entry) bool {
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "IsLDAPUserInDisabledGroup")
defer span.End()
span.SetAttributes(attribute.String("identity.config.disable_mechanism", i.User.DisableMechanism))
span.SetStatus(codes.Ok, "")
// Check if we need to do this here because the configuration is local to Identity.
if i.User.DisableMechanism != "group" {
return false
@@ -316,11 +327,15 @@ func (i *Identity) IsLDAPUserInDisabledGroup(log *zerolog.Logger, lc ldap.Client
[]string{i.Group.Schema.ID},
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
log.Debug().Str("backend", "ldap").Str("basedn", i.Group.LocalDisabledDN).Str("filter", filter).Int("scope", i.Group.scopeVal).Msg("LDAP Search")
sr, err := lc.Search(searchRequest)
if err != nil {
log.Error().Str("backend", "ldap").Err(err).Str("filter", filter).Msg("Error looking up error group")
// Err on the side of caution.
span.SetAttributes(attribute.String("ldap.error", err.Error()))
span.SetStatus(codes.Error, "")
return true
}
@@ -329,9 +344,14 @@ func (i *Identity) IsLDAPUserInDisabledGroup(log *zerolog.Logger, lc ldap.Client
// GetLDAPUserGroups looks up the group member ship of the supplied LDAP user entry.
// Returns a slice of strings with groupids
func (i *Identity) GetLDAPUserGroups(log *zerolog.Logger, lc ldap.Client, userEntry *ldap.Entry) ([]string, error) {
func (i *Identity) GetLDAPUserGroups(ctx context.Context, lc ldap.Client, userEntry *ldap.Entry) ([]string, error) {
var memberValue string
log := appctx.GetLogger(ctx)
_, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPUserGroups")
defer span.End()
if strings.ToLower(i.Group.Objectclass) == "posixgroup" {
// posixGroup usually means that the member attribute just contains the username
memberValue = userEntry.GetEqualFoldAttributeValue(i.User.Schema.Username)
@@ -350,11 +370,16 @@ func (i *Identity) GetLDAPUserGroups(log *zerolog.Logger, lc ldap.Client, userEn
)
log.Debug().Str("backend", "ldap").Str("basedn", i.Group.BaseDN).Str("filter", filter).Int("scope", i.Group.scopeVal).Msg("LDAP Search")
setLDAPSearchSpanAttributes(span, searchRequest)
sr, err := lc.Search(searchRequest)
if err != nil {
log.Debug().Str("backend", "ldap").Err(err).Str("filter", filter).Msg("Error looking up group memberships")
span.SetAttributes(attribute.String("ldap.error", err.Error()))
span.SetStatus(codes.Error, "")
return []string{}, err
}
span.SetStatus(codes.Ok, "")
span.SetAttributes(attribute.Int("ldap.result_count", len(sr.Entries)))
groups := make([]string, 0, len(sr.Entries))
for _, entry := range sr.Entries {
@@ -380,29 +405,32 @@ func (i *Identity) GetLDAPUserGroups(log *zerolog.Logger, lc ldap.Client, userEn
// GetLDAPGroupByID looks up a group by the supplied Id. Returns the corresponding
// ldap.Entry
func (i *Identity) GetLDAPGroupByID(log *zerolog.Logger, lc ldap.Client, id string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPGroupByID(ctx context.Context, lc ldap.Client, id string) (*ldap.Entry, error) {
var filter string
var err error
if filter, err = i.getGroupFilter(id); err != nil {
return nil, err
}
return i.GetLDAPGroupByFilter(log, lc, filter)
return i.GetLDAPGroupByFilter(ctx, lc, filter)
}
// GetLDAPGroupByAttribute looks up a single group by attribute (can be "mail", "gid_number",
// "display_name", "group_name", "group_id"). Returns the corresponding ldap.Entry
func (i *Identity) GetLDAPGroupByAttribute(log *zerolog.Logger, lc ldap.Client, attribute, value string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPGroupByAttribute(ctx context.Context, lc ldap.Client, attribute, value string) (*ldap.Entry, error) {
var filter string
var err error
if filter, err = i.getGroupAttributeFilter(attribute, value); err != nil {
return nil, err
}
return i.GetLDAPGroupByFilter(log, lc, filter)
return i.GetLDAPGroupByFilter(ctx, lc, filter)
}
// GetLDAPGroupByFilter looks up a single group by the supplied LDAP filter
// returns the corresponding ldap.Entry
func (i *Identity) GetLDAPGroupByFilter(log *zerolog.Logger, lc ldap.Client, filter string) (*ldap.Entry, error) {
func (i *Identity) GetLDAPGroupByFilter(ctx context.Context, lc ldap.Client, filter string) (*ldap.Entry, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPGroupByFilter")
defer span.End()
log := appctx.GetLogger(ctx)
searchRequest := ldap.NewSearchRequest(
i.Group.BaseDN, i.Group.scopeVal, ldap.NeverDerefAliases, 1, 0, false,
filter,
@@ -416,6 +444,7 @@ func (i *Identity) GetLDAPGroupByFilter(log *zerolog.Logger, lc ldap.Client, fil
},
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
log.Debug().Str("backend", "ldap").Str("basedn", i.Group.BaseDN).Str("filter", filter).Int("scope", i.Group.scopeVal).Msg("LDAP Search")
res, err := lc.Search(searchRequest)
@@ -427,18 +456,23 @@ func (i *Identity) GetLDAPGroupByFilter(log *zerolog.Logger, lc ldap.Client, fil
errmsg = fmt.Sprintf("too many results searching for group '%s'", filter)
}
}
span.SetAttributes(attribute.String("ldap.error", errmsg))
span.SetStatus(codes.Error, "")
return nil, errtypes.NotFound(errmsg)
}
if len(res.Entries) == 0 {
return nil, errtypes.NotFound(filter)
}
span.SetStatus(codes.Ok, "")
return res.Entries[0], nil
}
// GetLDAPGroups searches for groups using a prefix-substring match on the group
// attributes. Returns a slice of matching ldap.Entries
func (i *Identity) GetLDAPGroups(log *zerolog.Logger, lc ldap.Client, query string) ([]*ldap.Entry, error) {
func (i *Identity) GetLDAPGroups(ctx context.Context, lc ldap.Client, query string) ([]*ldap.Entry, error) {
ctx, span := appctx.GetTracerProvider(ctx).Tracer(tracerName).Start(ctx, "GetLDAPGroups")
defer span.End()
log := appctx.GetLogger(ctx)
searchRequest := ldap.NewSearchRequest(
i.Group.BaseDN,
ldap.ScopeWholeSubtree, ldap.NeverDerefAliases, 0, 0, false,
@@ -452,18 +486,22 @@ func (i *Identity) GetLDAPGroups(log *zerolog.Logger, lc ldap.Client, query stri
},
nil,
)
setLDAPSearchSpanAttributes(span, searchRequest)
sr, err := lc.Search(searchRequest)
if err != nil {
span.SetAttributes(attribute.String("ldap.error", err.Error()))
span.SetStatus(codes.Error, "")
log.Debug().Str("backend", "ldap").Err(err).Str("query", query).Msg("Error search for groups")
return nil, errtypes.NotFound(query)
}
span.SetStatus(codes.Ok, "")
return sr.Entries, nil
}
// GetLDAPGroupMembers looks up all members of the supplied LDAP group entry and returns the
// corresponding LDAP user entries
func (i *Identity) GetLDAPGroupMembers(log *zerolog.Logger, lc ldap.Client, group *ldap.Entry) ([]*ldap.Entry, error) {
func (i *Identity) GetLDAPGroupMembers(ctx context.Context, lc ldap.Client, group *ldap.Entry) ([]*ldap.Entry, error) {
log := appctx.GetLogger(ctx)
members := group.GetEqualFoldAttributeValues(i.Group.Schema.Member)
log.Debug().Str("dn", group.DN).Interface("member", members).Msg("Get Group members")
memberEntries := make([]*ldap.Entry, 0, len(members))
@@ -471,9 +509,9 @@ func (i *Identity) GetLDAPGroupMembers(log *zerolog.Logger, lc ldap.Client, grou
var e *ldap.Entry
var err error
if strings.ToLower(i.Group.Objectclass) == "posixgroup" {
e, err = i.GetLDAPUserByAttribute(log, lc, "username", member)
e, err = i.GetLDAPUserByAttribute(ctx, lc, "username", member, "")
} else {
e, err = i.GetLDAPUserByDN(log, lc, member)
e, err = i.GetLDAPUserByDN(ctx, lc, member)
}
if err != nil {
log.Warn().Err(err).Interface("member", member).Msg("Failed read user entry for member")
@@ -493,28 +531,28 @@ func filterEscapeBinaryUUID(value uuid.UUID) string {
return filtered
}
func (i *Identity) getUserFilter(uid string) (string, error) {
func (i *Identity) getUserFilter(uid *identityUser.UserId) (string, error) {
var escapedUUID string
if i.User.Schema.IDIsOctetString {
id, err := uuid.Parse(uid)
id, err := uuid.Parse(uid.GetOpaqueId())
if err != nil {
err := errors.Wrap(err, fmt.Sprintf("error parsing OpaqueID '%s' as UUID", uid))
return "", err
}
escapedUUID = filterEscapeBinaryUUID(id)
} else {
escapedUUID = ldap.EscapeFilter(uid)
escapedUUID = ldap.EscapeFilter(uid.GetOpaqueId())
}
return fmt.Sprintf("(&%s(objectclass=%s)(%s=%s))",
return fmt.Sprintf("(&%s(objectclass=%s)%s(%s=%s))",
i.User.Filter,
i.User.Objectclass,
i.tenantFilter(uid.GetTenantId()),
i.User.Schema.ID,
escapedUUID,
), nil
}
func (i *Identity) getUserAttributeFilter(attribute, value string) (string, error) {
func (i *Identity) getUserAttributeFilter(attribute, value, tenantID string) (string, error) {
switch attribute {
case "mail":
attribute = i.User.Schema.Mail
@@ -541,15 +579,22 @@ func (i *Identity) getUserAttributeFilter(attribute, value string) (string, erro
} else {
value = ldap.EscapeFilter(value)
}
return fmt.Sprintf("(&%s(objectclass=%s)(%s=%s)%s)",
return fmt.Sprintf("(&%s(objectclass=%s)(%s=%s)%s%s)",
i.User.Filter,
i.User.Objectclass,
attribute,
value,
i.tenantFilter(tenantID),
i.disabledFilter(),
), nil
}
func (i *Identity) tenantFilter(tenantID string) string {
if tenantID != "" && i.User.Schema.TenantID != "" {
return fmt.Sprintf("(%s=%s)", i.User.Schema.TenantID, ldap.EscapeFilter(tenantID))
}
return ""
}
func (i *Identity) disabledFilter() string {
if i.User.DisableMechanism == "attribute" {
return fmt.Sprintf("(!(%s=FALSE))", i.User.EnabledProperty)
@@ -580,14 +625,10 @@ func (i *Identity) getUserFindFilter(query, tenantID string) string {
// substring search for UUID is not possible
filter = fmt.Sprintf("(|%s(%s=%s))", filter, i.User.Schema.ID, ldap.EscapeFilter(query))
if tenantID != "" {
// If a tenant ID is provided, we AND a filter for the tenant ID
filter = fmt.Sprintf("(&%s(%s=%s))", filter, i.User.Schema.TenantID, ldap.EscapeFilter(tenantID))
}
return fmt.Sprintf("(&%s(objectclass=%s)%s)",
return fmt.Sprintf("(&%s(objectclass=%s)%s%s)",
i.User.Filter,
i.User.Objectclass,
i.tenantFilter(tenantID),
filter,
)
}
@@ -727,3 +768,40 @@ func (i *Identity) GetUserType(userEntry *ldap.Entry) identityUser.UserType {
return identityUser.UserType_USER_TYPE_PRIMARY
}
}
func (i *Identity) getUserLDAPAttrTypes() []string {
// The are the attributes we request unconditionally when looking up users
// as they are needed to populate a user object
attrs := []string{
i.User.Schema.ID,
i.User.Schema.Username,
i.User.Schema.Mail,
i.User.Schema.DisplayName,
}
// Only add optional attributes if they are configured
if i.User.Schema.UIDNumber != "" {
attrs = append(attrs, i.User.Schema.UIDNumber)
}
if i.User.Schema.GIDNumber != "" {
attrs = append(attrs, i.User.Schema.GIDNumber)
}
if i.User.Schema.TenantID != "" {
attrs = append(attrs, i.User.Schema.TenantID)
}
if i.User.EnabledProperty != "" {
attrs = append(attrs, i.User.EnabledProperty)
}
if i.User.UserTypeProperty != "" {
attrs = append(attrs, i.User.UserTypeProperty)
}
return attrs
}
func setLDAPSearchSpanAttributes(span trace.Span, request *ldap.SearchRequest) {
span.SetAttributes(
attribute.String("ldap.basedn", request.BaseDN),
attribute.String("ldap.filter", request.Filter),
attribute.Int("ldap.scope", request.Scope),
attribute.Int("ldap.size_limit", request.SizeLimit),
)
}