Add basic config setting for LDAP education backend

require LDAP support for Education resources to be explicitly enabled.
Default to a NOOP implementation if disabled.
This commit is contained in:
Ralf Haferkamp
2022-12-13 15:49:56 +01:00
committed by Ralf Haferkamp
parent 795bc70546
commit b302af88f6
6 changed files with 137 additions and 11 deletions

View File

@@ -62,6 +62,21 @@ type LDAP struct {
GroupObjectClass string `yaml:"group_objectclass" env:"LDAP_GROUP_OBJECTCLASS;GRAPH_LDAP_GROUP_OBJECTCLASS" desc:"The object class to use for groups in the default group search filter ('groupOfNames'). "`
GroupNameAttribute string `yaml:"group_name_attribute" env:"LDAP_GROUP_SCHEMA_GROUPNAME;GRAPH_LDAP_GROUP_NAME_ATTRIBUTE" desc:"LDAP Attribute to use for the name of groups."`
GroupIDAttribute string `yaml:"group_id_attribute" env:"LDAP_GROUP_SCHEMA_ID;GRAPH_LDAP_GROUP_ID_ATTRIBUTE" desc:"LDAP Attribute to use as the unique id for groups. This should be a stable globally unique ID like a UUID."`
EducationResourcesEnabled bool `yaml:"education_resources_enabled" env:"LDAP_EDUCATION_RESOURCES_ENABLE;GRAPH_LDAP_EDUCATION_RESOURCES_ENABLED" desc:"enable LDAP support for managin education related resources"`
EducationConfig LDAPEducationConfig
}
// LDAPEducationConfig represents the LDAP configuration for education related resources
type LDAPEducationConfig struct {
SchoolBaseDN string `yaml:"school_base_dn" env:"LDAP_SCHOOL_BASE_DN;GRAPH_LDAP_SCHOOL_BASE_DN" desc:"Search base DN for looking up LDAP schools."`
SchoolSearchScope string `yaml:"school_search_scope" env:"LDAP_SCHOOL_SCOPE;GRAPH_LDAP_SCHOOL_SEARCH_SCOPE" desc:"LDAP search scope to use when looking up schools. Supported scopes are 'base', 'one' and 'sub'."`
SchoolFilter string `yaml:"school_filter" env:"LDAP_SCHOOL_FILTER;GRAPH_LDAP_SCHOOL_FILTER" desc:"LDAP filter to add to the default filters for school searches."`
SchoolObjectClass string `yaml:"school_objectclass" env:"LDAP_SCHOOL_OBJECTCLASS;GRAPH_LDAP_SCHOOL_OBJECTCLASS" desc:"The object class to use for schools in the default school search filter."`
SchoolNameAttribute string `yaml:"school_name_attribute" env:"LDAP_SCHOOL_SCHEMA_SCHOOLNAME;GRAPH_LDAP_SCHOOL_NAME_ATTRIBUTE" desc:"LDAP Attribute to use for the name of schools."`
SchoolIDAttribute string `yaml:"school_id_attribute" env:"LDAP_SCHOOL_SCHEMA_ID;GRAPH_LDAP_SCHOOL_ID_ATTRIBUTE" desc:"LDAP Attribute to use as the unique id for schools. This should be a stable globally unique ID like a UUID."`
}
type Identity struct {

View File

@@ -55,13 +55,14 @@ func DefaultConfig() *config.Config {
UserNameAttribute: "uid",
// FIXME: switch this to some more widely available attribute by default
// ideally this needs to be constant for the lifetime of a users
UserIDAttribute: "owncloudUUID",
GroupBaseDN: "ou=groups,o=libregraph-idm",
GroupSearchScope: "sub",
GroupFilter: "",
GroupObjectClass: "groupOfNames",
GroupNameAttribute: "cn",
GroupIDAttribute: "owncloudUUID",
UserIDAttribute: "owncloudUUID",
GroupBaseDN: "ou=groups,o=libregraph-idm",
GroupSearchScope: "sub",
GroupFilter: "",
GroupObjectClass: "groupOfNames",
GroupNameAttribute: "cn",
GroupIDAttribute: "owncloudUUID",
EducationResourcesEnabled: false,
},
},
Events: config.Events{

View File

@@ -40,6 +40,8 @@ type LDAP struct {
groupScope int
groupAttributeMap groupAttributeMap
educationConfig educationConfig
logger *log.Logger
conn ldap.Client
}
@@ -90,6 +92,11 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
return nil, fmt.Errorf("error configuring group scope: %w", err)
}
var educationConfig educationConfig
if educationConfig, err = newEducationConfig(config); err != nil {
return nil, fmt.Errorf("error setting up education resource config: %w", err)
}
return &LDAP{
useServerUUID: config.UseServerUUID,
usePwModifyExOp: config.UsePasswordModExOp,
@@ -103,6 +110,7 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD
groupObjectClass: config.GroupObjectClass,
groupScope: groupScope,
groupAttributeMap: gam,
educationConfig: educationConfig,
logger: logger,
conn: lc,
writeEnabled: config.WriteEnabled,

View File

@@ -2,12 +2,15 @@ package identity
import (
"context"
"fmt"
"net/url"
"github.com/go-ldap/ldap/v3"
libregraph "github.com/owncloud/libre-graph-api-go"
"github.com/owncloud/ocis/v2/services/graph/pkg/config"
)
type schoolConfig struct {
type educationConfig struct {
schoolBaseDN string
schoolFilter string
schoolObjectClass string
@@ -16,14 +19,37 @@ type schoolConfig struct {
}
type schoolAttributeMap struct {
displayname string
displayName string
schoolNumber string
id string
}
func defaultEducationConfig() educationConfig {
return educationConfig{
schoolObjectClass: "ocEducationSchool",
schoolScope: ldap.ScopeWholeSubtree,
schoolAttributeMap: newSchoolAttributeMap(),
}
}
func newEducationConfig(config config.LDAP) (educationConfig, error) {
if config.EducationResourcesEnabled {
var err error
eduCfg := defaultEducationConfig()
eduCfg.schoolBaseDN = config.EducationConfig.SchoolBaseDN
if config.EducationConfig.SchoolSearchScope != "" {
if eduCfg.schoolScope, err = stringToScope(config.EducationConfig.SchoolSearchScope); err != nil {
return educationConfig{}, fmt.Errorf("error configuring school search scope: %w", err)
}
}
return eduCfg, nil
}
return educationConfig{}, nil
}
func newSchoolAttributeMap() schoolAttributeMap {
return schoolAttributeMap{
displayname: "ou",
displayName: "ou",
schoolNumber: "ocEducationSchoolNumber",
id: "owncloudUUID",
}

View File

@@ -0,0 +1,71 @@
package identity
import (
"context"
"net/url"
libregraph "github.com/owncloud/libre-graph-api-go"
)
// NOOP is a dummy EducationBackend, doing nothing
type NOOP struct{}
// CreateSchool creates the supplied school in the identity backend.
func (i *NOOP) CreateSchool(ctx context.Context, school libregraph.EducationSchool) (*libregraph.EducationSchool, error) {
return nil, errNotImplemented
}
// DeleteSchool deletes a given school, identified by id
func (i *NOOP) DeleteSchool(ctx context.Context, id string) error {
return errNotImplemented
}
// GetSchool implements the EducationBackend interface for the NOOP backend.
func (i *NOOP) GetSchool(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.EducationSchool, error) {
return nil, errNotImplemented
}
// GetSchools implements the EducationBackend interface for the NOOP backend.
func (i *NOOP) GetSchools(ctx context.Context, queryParam url.Values) ([]*libregraph.EducationSchool, error) {
return nil, errNotImplemented
}
// GetSchoolMembers implements the EducationBackend interface for the NOOP backend.
func (i *NOOP) GetSchoolMembers(ctx context.Context, id string) ([]*libregraph.EducationUser, error) {
return nil, errNotImplemented
}
// AddMembersToSchool adds new members (reference by a slice of IDs) to supplied school in the identity backend.
func (i *NOOP) AddMembersToSchool(ctx context.Context, schoolID string, memberID []string) error {
return errNotImplemented
}
// RemoveMemberFromSchool removes a single member (by ID) from a school
func (i *NOOP) RemoveMemberFromSchool(ctx context.Context, schoolID string, memberID string) error {
return errNotImplemented
}
// CreateEducationUser creates a given education user in the identity backend.
func (i *NOOP) CreateEducationUser(ctx context.Context, user libregraph.EducationUser) (*libregraph.EducationUser, error) {
return nil, errNotImplemented
}
// DeleteEducationUser deletes a given educationuser, identified by username or id, from the backend
func (i *NOOP) DeleteEducationUser(ctx context.Context, nameOrID string) error {
return errNotImplemented
}
// UpdateEducationUser applies changes to given education user, identified by username or id
func (i *NOOP) UpdateEducationUser(ctx context.Context, nameOrID string, user libregraph.EducationUser) (*libregraph.EducationUser, error) {
return nil, errNotImplemented
}
// GetEducationUser implements the EducationBackend interface for the NOOP backend.
func (i *NOOP) GetEducationUser(ctx context.Context, nameOrID string, queryParam url.Values) (*libregraph.EducationUser, error) {
return nil, errNotImplemented
}
// GetEducationUsers implements the EducationBackend interface for the NOOP backend.
func (i *NOOP) GetEducationUsers(ctx context.Context, queryParam url.Values) ([]*libregraph.EducationUser, error) {
return nil, errNotImplemented
}

View File

@@ -146,7 +146,12 @@ func NewService(opts ...Option) Service {
}
svc.identityBackend = lb
if options.IdentityEducationBackend == nil {
svc.identityEducationBackend = lb
if options.Config.Identity.LDAP.EducationResourcesEnabled {
svc.identityEducationBackend = lb
} else {
noop := &identity.NOOP{}
svc.identityEducationBackend = noop
}
}
default:
options.Logger.Error().Msgf("Unknown Identity Backend: '%s'", options.Config.Identity.Backend)