Bump reva to latest main
to get https://github.com/opencloud-eu/reva/pull/339
This commit is contained in:
committed by
Ralf Haferkamp
parent
a5e0c1ec4b
commit
65228f3188
Generated
Vendored
+11
-2
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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
@@ -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{
|
||||
|
||||
+7
-1
@@ -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"`
|
||||
|
||||
Generated
Vendored
+8
-1
@@ -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
@@ -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
@@ -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
@@ -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),
|
||||
)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user