From e982da5efe36a3d5ece07869a11d12d0d93c09fe Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 6 Apr 2022 17:46:38 +0200 Subject: [PATCH] adapt for new LDAP config --- go.mod | 2 + go.sum | 4 +- graph/pkg/config/config.go | 32 ++-- graph/pkg/config/defaults/defaultconfig.go | 6 +- graph/pkg/identity/ldap.go | 14 +- idp/pkg/config/config.go | 19 +-- idp/pkg/config/defaults/defaultconfig.go | 5 +- idp/pkg/service/v0/service.go | 6 +- storage/pkg/command/authbasic.go | 27 +--- storage/pkg/command/groups.go | 30 +--- storage/pkg/command/ldapcfg.go | 60 +++++++ storage/pkg/command/users.go | 32 ++-- storage/pkg/config/config.go | 159 ++++++++++--------- storage/pkg/config/defaults/defaultconfig.go | 41 +++-- 14 files changed, 239 insertions(+), 198 deletions(-) create mode 100644 storage/pkg/command/ldapcfg.go diff --git a/go.mod b/go.mod index 6df2c382211..532d9512b83 100644 --- a/go.mod +++ b/go.mod @@ -271,3 +271,5 @@ require ( // we need to use a fork to make the windows build pass replace github.com/pkg/xattr => github.com/micbar/xattr v0.4.6-0.20220215112335-88e74d648fb7 + +replace github.com/cs3org/reva/v2 => github.com/rhafer/reva/v2 v2.0.0-20220405124942-8293b7a72a70 diff --git a/go.sum b/go.sum index c0e42ce0bf0..34776cc254b 100644 --- a/go.sum +++ b/go.sum @@ -337,8 +337,6 @@ github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD9 github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4= github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f h1:emnlOWc1s2gx77MViLnZH9yh5TRHKsykRu6rJjx3lkM= github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f/go.mod h1:UXha4TguuB52H14EMoSsCqDj7k8a/t7g4gVP+bgY5LY= -github.com/cs3org/reva/v2 v2.0.0-20220404075659-19fd0b28297b h1:CqHYID4t286wle5kXcFfUtxxw6Vz0XlbGCiB/Z8rDbI= -github.com/cs3org/reva/v2 v2.0.0-20220404075659-19fd0b28297b/go.mod h1:1siLO6MV57uSyzQxPbfM6qNA9NP6aagN3/yKOE/FwtM= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8 h1:Z9lwXumT5ACSmJ7WGnFl+OMLLjpz5uR2fyz7dC255FI= github.com/cubewise-code/go-mime v0.0.0-20200519001935-8c5762b177d8/go.mod h1:4abs/jPXcmJzYoYGF91JF9Uq9s/KL5n1jvFDix8KcqY= github.com/cyberdelia/templates v0.0.0-20141128023046-ca7fffd4298c/go.mod h1:GyV+0YP4qX0UQ7r2MoYZ+AvYDp12OF5yg4q8rGnyNh4= @@ -1217,6 +1215,8 @@ github.com/prometheus/statsd_exporter v0.22.4/go.mod h1:N4Z1+iSqc9rnxlT1N8Qn3l65 github.com/prometheus/tsdb v0.7.1/go.mod h1:qhTCs0VvXwvX/y3TZrWD7rabWM+ijKTux40TwIPHuXU= github.com/rainycape/memcache v0.0.0-20150622160815-1031fa0ce2f2/go.mod h1:7tZKcyumwBO6qip7RNQ5r77yrssm9bfCowcLEBcU5IA= github.com/rcrowley/go-metrics v0.0.0-20181016184325-3113b8401b8a/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4= +github.com/rhafer/reva/v2 v2.0.0-20220405124942-8293b7a72a70 h1:cLMe1OP/KxFs4oxOCdwz+Tujpjv9WiwlLUbF2fYxXbY= +github.com/rhafer/reva/v2 v2.0.0-20220405124942-8293b7a72a70/go.mod h1:1siLO6MV57uSyzQxPbfM6qNA9NP6aagN3/yKOE/FwtM= github.com/rickb777/date v1.12.4/go.mod h1:xP0eo/I5qmUt97yRGClHZfyLZ3ikMw6v6SU5MOGZTE0= github.com/rickb777/date v1.17.0 h1:Qk1MUtTLFfIWYhRaNRyk1t7LmjfkjOEELacQPsoh7Nw= github.com/rickb777/date v1.17.0/go.mod h1:b3AnLwjEdg1YWLUFnAd/lUq3JDJmMRXi/Onm8q0zlQg= diff --git a/graph/pkg/config/config.go b/graph/pkg/config/config.go index 3501a30a032..c34dae9970e 100644 --- a/graph/pkg/config/config.go +++ b/graph/pkg/config/config.go @@ -36,26 +36,28 @@ type Spaces struct { } type LDAP struct { - URI string `yaml:"uri" env:"GRAPH_LDAP_URI"` + URI string `yaml:"uri" env:"LDAP_URI;GRAPH_LDAP_URI"` Insecure bool `yaml:"insecure" env:"OCIS_INSECURE;GRAPH_LDAP_INSECURE"` - BindDN string `yaml:"bind_dn" env:"GRAPH_LDAP_BIND_DN"` - BindPassword string `yaml:"bind_password" env:"GRAPH_LDAP_BIND_PASSWORD"` + BindDN string `yaml:"bind_dn" env:"LDAP_BIND_DN;GRAPH_LDAP_BIND_DN"` + BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;GRAPH_LDAP_BIND_PASSWORD"` UseServerUUID bool `yaml:"use_server_uuid" env:"GRAPH_LDAP_SERVER_UUID"` WriteEnabled bool `yaml:"write_enabled" env:"GRAPH_LDAP_SERVER_WRITE_ENABLED"` - UserBaseDN string `yaml:"user_base_dn" env:"GRAPH_LDAP_USER_BASE_DN"` - UserSearchScope string `yaml:"user_search_scope" env:"GRAPH_LDAP_USER_SCOPE"` - UserFilter string `yaml:"user_filter" env:"GRAPH_LDAP_USER_FILTER"` - UserEmailAttribute string `yaml:"user_mail_attribute" env:"GRAPH_LDAP_USER_EMAIL_ATTRIBUTE"` - UserDisplayNameAttribute string `yaml:"user_displayname_attribute" env:"GRAPH_LDAP_USER_DISPLAYNAME_ATTRIBUTE"` - UserNameAttribute string `yaml:"user_name_attribute" env:"GRAPH_LDAP_USER_NAME_ATTRIBUTE"` - UserIDAttribute string `yaml:"user_id_attribute" env:"GRAPH_LDAP_USER_UID_ATTRIBUTE"` + UserBaseDN string `yaml:"user_base_dn" env:"LDAP_USER_BASE_DN;GRAPH_LDAP_USER_BASE_DN"` + UserSearchScope string `yaml:"user_search_scope" env:"LDAP_USER_SCOPE;GRAPH_LDAP_USER_SCOPE"` + UserFilter string `yaml:"user_filter" env:"LDAP_USER_FILTER;GRAPH_LDAP_USER_FILTER"` + UserObjectClass string `yaml:"user_objectclass" env:"LDAP_USER_OBJECTCLASS;GRAPH_LDAP_USER_OBJECTCLASS"` + UserEmailAttribute string `yaml:"user_mail_attribute" env:"LDAP_USER_SCHEMA_MAIL;GRAPH_LDAP_USER_EMAIL_ATTRIBUTE"` + UserDisplayNameAttribute string `yaml:"user_displayname_attribute" env:"LDAP_USER_SCHEMA_DISPLAY_NAME;GRAPH_LDAP_USER_DISPLAYNAME_ATTRIBUTE"` + UserNameAttribute string `yaml:"user_name_attribute" env:"LDAP_USER_SCHEMA_USERNAME;GRAPH_LDAP_USER_NAME_ATTRIBUTE"` + UserIDAttribute string `yaml:"user_id_attribute" env:"LDAP_USER_SCHEMA_ID;GRAPH_LDAP_USER_UID_ATTRIBUTE"` - GroupBaseDN string `yaml:"group_base_dn" env:"GRAPH_LDAP_GROUP_BASE_DN"` - GroupSearchScope string `yaml:"group_search_scope" env:"GRAPH_LDAP_GROUP_SEARCH_SCOPE"` - GroupFilter string `yaml:"group_filter" env:"GRAPH_LDAP_GROUP_FILTER"` - GroupNameAttribute string `yaml:"group_name_attribute" env:"GRAPH_LDAP_GROUP_NAME_ATTRIBUTE"` - GroupIDAttribute string `yaml:"group_id_attribute" env:"GRAPH_LDAP_GROUP_ID_ATTRIBUTE"` + GroupBaseDN string `yaml:"group_base_dn" env:"LDAP_GROUP_BASE_DN;GRAPH_LDAP_GROUP_BASE_DN"` + GroupSearchScope string `yaml:"group_search_scope" env:"LDAP_GROUP_SCOPE;GRAPH_LDAP_GROUP_SEARCH_SCOPE"` + GroupFilter string `yaml:"group_filter" env:"LDAP_GROUP_FILTER;GRAPH_LDAP_GROUP_FILTER"` + GroupObjectClass string `yaml:"group_objectclass" env:"LDAP_GROUP_OBJECTCLASS;GRAPH_LDAP_GROUP_OBJECTCLASS"` + GroupNameAttribute string `yaml:"group_name_attribute" env:"LDAP_GROUP_SCHEMA_GROUPNAME;GRAPH_LDAP_GROUP_NAME_ATTRIBUTE"` + GroupIDAttribute string `yaml:"group_id_attribute" env:"LDAP_GROUP_SCHEMA_ID;GRAPH_LDAP_GROUP_ID_ATTRIBUTE"` } type Identity struct { diff --git a/graph/pkg/config/defaults/defaultconfig.go b/graph/pkg/config/defaults/defaultconfig.go index 9c2eba50cb8..e73353b09fb 100644 --- a/graph/pkg/config/defaults/defaultconfig.go +++ b/graph/pkg/config/defaults/defaultconfig.go @@ -43,7 +43,8 @@ func DefaultConfig() *config.Config { WriteEnabled: false, UserBaseDN: "ou=users,dc=ocis,dc=test", UserSearchScope: "sub", - UserFilter: "(objectClass=inetOrgPerson)", + UserFilter: "", + UserObjectClass: "inetOrgPerson", UserEmailAttribute: "mail", UserDisplayNameAttribute: "displayName", UserNameAttribute: "uid", @@ -52,7 +53,8 @@ func DefaultConfig() *config.Config { UserIDAttribute: "owncloudUUID", GroupBaseDN: "ou=groups,dc=ocis,dc=test", GroupSearchScope: "sub", - GroupFilter: "(objectclass=groupOfNames)", + GroupFilter: "", + GroupObjectClass: "groupOfNames", GroupNameAttribute: "cn", GroupIDAttribute: "owncloudUUID", }, diff --git a/graph/pkg/identity/ldap.go b/graph/pkg/identity/ldap.go index 5a9601d039a..882ea91af3b 100644 --- a/graph/pkg/identity/ldap.go +++ b/graph/pkg/identity/ldap.go @@ -27,11 +27,13 @@ type LDAP struct { userBaseDN string userFilter string + userObjectClass string userScope int userAttributeMap userAttributeMap groupBaseDN string groupFilter string + groupObjectClass string groupScope int groupAttributeMap groupAttributeMap @@ -89,10 +91,12 @@ func NewLDAPBackend(lc ldap.Client, config config.LDAP, logger *log.Logger) (*LD useServerUUID: config.UseServerUUID, userBaseDN: config.UserBaseDN, userFilter: config.UserFilter, + userObjectClass: config.UserObjectClass, userScope: userScope, userAttributeMap: uam, groupBaseDN: config.GroupBaseDN, groupFilter: config.GroupFilter, + groupObjectClass: config.GroupObjectClass, groupScope: groupScope, groupAttributeMap: gam, logger: logger, @@ -311,7 +315,7 @@ func (i *LDAP) getLDAPUserByNameOrID(nameOrID string) (*ldap.Entry, error) { func (i *LDAP) getLDAPUserByFilter(filter string) (*ldap.Entry, error) { searchRequest := ldap.NewSearchRequest( i.userBaseDN, i.userScope, ldap.NeverDerefAliases, 1, 0, false, - fmt.Sprintf("(&%s%s)", i.userFilter, filter), + fmt.Sprintf("(&%s(objectClass=%s)%s)", i.userFilter, i.userObjectClass, filter), []string{ i.userAttributeMap.displayName, i.userAttributeMap.id, @@ -357,7 +361,7 @@ func (i *LDAP) GetUsers(ctx context.Context, queryParam url.Values) ([]*libregra if search == "" { search = queryParam.Get("$search") } - userFilter := i.userFilter + userFilter := fmt.Sprintf("%s(objectClass=%s)", i.userFilter, i.userObjectClass) if search != "" { search = ldap.EscapeFilter(search) userFilter = fmt.Sprintf( @@ -428,7 +432,7 @@ func (i *LDAP) getLDAPGroupByFilter(filter string, requestMembers bool) (*ldap.E // Search for LDAP Groups matching the specified filter, if requestMembers is true the groupMemberShip // attribute will be part of the result attributes. The LDAP filter is combined with the configured groupFilter -// resulting in a filter like "(&(LDAP.groupFilter)())" +// resulting in a filter like "(&(LDAP.groupFilter)(objectClass=LDAP.groupObjectClass)())" func (i *LDAP) getLDAPGroupsByFilter(filter string, requestMembers, single bool) ([]*ldap.Entry, error) { attrs := []string{ i.groupAttributeMap.name, @@ -445,7 +449,7 @@ func (i *LDAP) getLDAPGroupsByFilter(filter string, requestMembers, single bool) } searchRequest := ldap.NewSearchRequest( i.groupBaseDN, i.groupScope, ldap.NeverDerefAliases, sizelimit, 0, false, - fmt.Sprintf("(&%s%s)", i.groupFilter, filter), + fmt.Sprintf("(&%s(objectClass=%s)%s)", i.groupFilter, i.groupObjectClass, filter), attrs, nil, ) @@ -511,7 +515,7 @@ func (i *LDAP) GetGroups(ctx context.Context, queryParam url.Values) ([]*libregr if search == "" { search = queryParam.Get("$search") } - groupFilter := i.groupFilter + groupFilter := fmt.Sprintf("%s(objectClass=%s)", i.groupFilter, i.groupObjectClass) if search != "" { search = ldap.EscapeFilter(search) groupFilter = fmt.Sprintf( diff --git a/idp/pkg/config/config.go b/idp/pkg/config/config.go index 1b924c9d251..83bd84554d0 100644 --- a/idp/pkg/config/config.go +++ b/idp/pkg/config/config.go @@ -27,21 +27,22 @@ type Config struct { // Ldap defines the available LDAP configuration. type Ldap struct { - URI string `yaml:"uri" env:"IDP_LDAP_URI"` + URI string `yaml:"uri" env:"LDAP_URI;IDP_LDAP_URI"` - BindDN string `yaml:"bind_dn" env:"IDP_LDAP_BIND_DN"` - BindPassword string `yaml:"bind_password" env:"IDP_LDAP_BIND_PASSWORD"` + BindDN string `yaml:"bind_dn" env:"LDAP_BIND_DN;IDP_LDAP_BIND_DN"` + BindPassword string `yaml:"bind_password" env:"LDAP_BIND_PASSWORD;IDP_LDAP_BIND_PASSWORD"` - BaseDN string `yaml:"base_dn" env:"IDP_LDAP_BASE_DN"` - Scope string `yaml:"scope" env:"IDP_LDAP_SCOPE"` + BaseDN string `yaml:"base_dn" env:"LDAP_USER_BASE_DN,IDP_LDAP_BASE_DN"` + Scope string `yaml:"scope" env:"LDAP_USER_SCOPE;IDP_LDAP_SCOPE"` LoginAttribute string `yaml:"login_attribute" env:"IDP_LDAP_LOGIN_ATTRIBUTE"` - EmailAttribute string `yaml:"email_attribute" env:"IDP_LDAP_EMAIL_ATTRIBUTE"` - NameAttribute string `yaml:"name_attribute" env:"IDP_LDAP_NAME_ATTRIBUTE"` - UUIDAttribute string `yaml:"uuid_attribute" env:"IDP_LDAP_UUID_ATTRIBUTE"` + EmailAttribute string `yaml:"email_attribute" env:"LDAP_USER_SCHEMA_MAIL;IDP_LDAP_EMAIL_ATTRIBUTE"` + NameAttribute string `yaml:"name_attribute" env:"LDAP_USER_SCHEMA_USERNAME;IDP_LDAP_NAME_ATTRIBUTE"` + UUIDAttribute string `yaml:"uuid_attribute" env:"LDAP_USER_SCHEMA_ID;IDP_LDAP_UUID_ATTRIBUTE"` UUIDAttributeType string `yaml:"uuid_attribute_type" env:"IDP_LDAP_UUID_ATTRIBUTE_TYPE"` - Filter string `yaml:"filter" env:"IDP_LDAP_FILTER"` + Filter string `yaml:"filter" env:"LDAP_USER_FILTER;IDP_LDAP_FILTER"` + ObjectClass string `yaml:"objectclass" env:"LDAP_USER_OBJECTCLASS;IDP_LDAP_OBJECTCLASS"` } // Asset defines the available asset configuration. diff --git a/idp/pkg/config/defaults/defaultconfig.go b/idp/pkg/config/defaults/defaultconfig.go index e965278665b..f35a70a6cfd 100644 --- a/idp/pkg/config/defaults/defaultconfig.go +++ b/idp/pkg/config/defaults/defaultconfig.go @@ -75,10 +75,11 @@ func DefaultConfig() *config.Config { Scope: "sub", LoginAttribute: "cn", EmailAttribute: "mail", - NameAttribute: "sn", + NameAttribute: "displayName", UUIDAttribute: "uid", UUIDAttributeType: "text", - Filter: "(objectClass=posixaccount)", + Filter: "", + ObjectClass: "posixAccount", }, } } diff --git a/idp/pkg/service/v0/service.go b/idp/pkg/service/v0/service.go index 0598f0b59d3..3d4bd80eec2 100644 --- a/idp/pkg/service/v0/service.go +++ b/idp/pkg/service/v0/service.go @@ -124,6 +124,10 @@ func createConfigsIfNotExist(assets http.FileSystem, filePath, ocisURL string) e // Init vars which are currently not accessible via idp api func initLicoInternalEnvVars(ldap *config.Ldap) error { + filter := fmt.Sprintf("(objectclass=%s)", ldap.ObjectClass) + if ldap.Filter != "" { + filter = fmt.Sprintf("(&%s%s)", ldap.Filter, filter) + } var defaults = map[string]string{ "LDAP_URI": ldap.URI, "LDAP_BINDDN": ldap.BindDN, @@ -135,7 +139,7 @@ func initLicoInternalEnvVars(ldap *config.Ldap) error { "LDAP_NAME_ATTRIBUTE": ldap.NameAttribute, "LDAP_UUID_ATTRIBUTE": ldap.UUIDAttribute, "LDAP_UUID_ATTRIBUTE_TYPE": ldap.UUIDAttributeType, - "LDAP_FILTER": ldap.Filter, + "LDAP_FILTER": filter, } for k, v := range defaults { diff --git a/storage/pkg/command/authbasic.go b/storage/pkg/command/authbasic.go index 375f3587128..30b0945a969 100644 --- a/storage/pkg/command/authbasic.go +++ b/storage/pkg/command/authbasic.go @@ -50,6 +50,13 @@ func AuthBasic(cfg *config.Config) *cli.Command { Interface("reva-config", rcfg). Msg("config") + if cfg.Reva.AuthProvider.Driver == "ldap" { + if err := waitForLDAPCA(logger, &cfg.Reva.LDAP); err != nil { + logger.Error().Err(err).Msg("The configured LDAP CA cert does not exist") + return err + } + } + gr.Add(func() error { runtime.RunWithOptions(rcfg, pidFile, runtime.WithLogger(&logger.Logger)) return nil @@ -113,25 +120,7 @@ func authBasicConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]in "json": map[string]interface{}{ "users": cfg.Reva.AuthProvider.JSON, }, - "ldap": map[string]interface{}{ - "hostname": cfg.Reva.LDAP.Hostname, - "port": cfg.Reva.LDAP.Port, - "cacert": cfg.Reva.LDAP.CACert, - "insecure": cfg.Reva.LDAP.Insecure, - "base_dn": cfg.Reva.LDAP.BaseDN, - "loginfilter": cfg.Reva.LDAP.LoginFilter, - "bind_username": cfg.Reva.LDAP.BindDN, - "bind_password": cfg.Reva.LDAP.BindPassword, - "idp": cfg.Reva.LDAP.IDP, - "gatewaysvc": cfg.Reva.Gateway.Endpoint, - "schema": map[string]interface{}{ - "dn": "dn", - "uid": cfg.Reva.LDAP.UserSchema.UID, - "mail": cfg.Reva.LDAP.UserSchema.Mail, - "displayName": cfg.Reva.LDAP.UserSchema.DisplayName, - "cn": cfg.Reva.LDAP.UserSchema.CN, - }, - }, + "ldap": ldapConfigFromString(cfg), "owncloudsql": map[string]interface{}{ "dbusername": cfg.Reva.UserOwnCloudSQL.DBUsername, "dbpassword": cfg.Reva.UserOwnCloudSQL.DBPassword, diff --git a/storage/pkg/command/groups.go b/storage/pkg/command/groups.go index a763dceea80..07a628ed828 100644 --- a/storage/pkg/command/groups.go +++ b/storage/pkg/command/groups.go @@ -46,6 +46,13 @@ func Groups(cfg *config.Config) *cli.Command { rcfg := groupsConfigFromStruct(c, cfg) + if cfg.Reva.Groups.Driver == "ldap" { + if err := waitForLDAPCA(logger, &cfg.Reva.LDAP); err != nil { + logger.Error().Err(err).Msg("The configured LDAP CA cert does not exist") + return err + } + } + gr.Add(func() error { runtime.RunWithOptions( rcfg, @@ -113,28 +120,7 @@ func groupsConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]inter "json": map[string]interface{}{ "groups": cfg.Reva.Groups.JSON, }, - "ldap": map[string]interface{}{ - "hostname": cfg.Reva.LDAP.Hostname, - "port": cfg.Reva.LDAP.Port, - "cacert": cfg.Reva.LDAP.CACert, - "insecure": cfg.Reva.LDAP.Insecure, - "base_dn": cfg.Reva.LDAP.BaseDN, - "groupfilter": cfg.Reva.LDAP.GroupFilter, - "attributefilter": cfg.Reva.LDAP.GroupAttributeFilter, - "findfilter": cfg.Reva.LDAP.GroupFindFilter, - "memberfilter": cfg.Reva.LDAP.GroupMemberFilter, - "bind_username": cfg.Reva.LDAP.BindDN, - "bind_password": cfg.Reva.LDAP.BindPassword, - "idp": cfg.Reva.LDAP.IDP, - "schema": map[string]interface{}{ - "dn": "dn", - "gid": cfg.Reva.LDAP.GroupSchema.GID, - "mail": cfg.Reva.LDAP.GroupSchema.Mail, - "displayName": cfg.Reva.LDAP.GroupSchema.DisplayName, - "cn": cfg.Reva.LDAP.GroupSchema.CN, - "gidNumber": cfg.Reva.LDAP.GroupSchema.GIDNumber, - }, - }, + "ldap": ldapConfigFromString(cfg), "rest": map[string]interface{}{ "client_id": cfg.Reva.UserGroupRest.ClientID, "client_secret": cfg.Reva.UserGroupRest.ClientSecret, diff --git a/storage/pkg/command/ldapcfg.go b/storage/pkg/command/ldapcfg.go new file mode 100644 index 00000000000..9d9e3941328 --- /dev/null +++ b/storage/pkg/command/ldapcfg.go @@ -0,0 +1,60 @@ +package command + +import ( + "errors" + "os" + "time" + + "github.com/owncloud/ocis/ocis-pkg/log" + "github.com/owncloud/ocis/storage/pkg/config" +) + +const caTimeout = 5 + +func ldapConfigFromString(cfg *config.Config) map[string]interface{} { + return map[string]interface{}{ + "uri": cfg.Reva.LDAP.URI, + "cacert": cfg.Reva.LDAP.CACert, + "insecure": cfg.Reva.LDAP.Insecure, + "bind_username": cfg.Reva.LDAP.BindDN, + "bind_password": cfg.Reva.LDAP.BindPassword, + "user_base_dn": cfg.Reva.LDAP.UserBaseDN, + "group_base_dn": cfg.Reva.LDAP.GroupBaseDN, + "user_filter": cfg.Reva.LDAP.UserFilter, + "group_filter": cfg.Reva.LDAP.GroupFilter, + "user_objectclass": cfg.Reva.LDAP.UserObjectClass, + "group_objectclass": cfg.Reva.LDAP.GroupObjectClass, + "login_attributes": cfg.Reva.LDAP.LoginAttributes, + "idp": cfg.Reva.LDAP.IDP, + "gatewaysvc": cfg.Reva.Gateway.Endpoint, + "user_schema": map[string]interface{}{ + "id": cfg.Reva.LDAP.UserSchema.ID, + "idIsOctetString": cfg.Reva.LDAP.UserSchema.IDIsOctetString, + "mail": cfg.Reva.LDAP.UserSchema.Mail, + "displayName": cfg.Reva.LDAP.UserSchema.DisplayName, + "userName": cfg.Reva.LDAP.UserSchema.Username, + }, + "group_schema": map[string]interface{}{ + "id": cfg.Reva.LDAP.GroupSchema.ID, + "idIsOctetString": cfg.Reva.LDAP.GroupSchema.IDIsOctetString, + "mail": cfg.Reva.LDAP.GroupSchema.Mail, + "displayName": cfg.Reva.LDAP.GroupSchema.DisplayName, + "groupName": cfg.Reva.LDAP.GroupSchema.Groupname, + "member": cfg.Reva.LDAP.GroupSchema.Member, + }, + } +} + +func waitForLDAPCA(log log.Logger, cfg *config.LDAP) error { + if !cfg.Insecure && cfg.CACert != "" { + if _, err := os.Stat(cfg.CACert); errors.Is(err, os.ErrNotExist) { + log.Warn().Str("LDAP CACert", cfg.CACert).Msgf("File does not exist. Waiting %d seconds for it to appear.", caTimeout) + time.Sleep(caTimeout * time.Second) + if _, err := os.Stat(cfg.CACert); errors.Is(err, os.ErrNotExist) { + log.Warn().Str("LDAP CACert", cfg.CACert).Msgf("File does still not exist after Timeout") + return err + } + } + } + return nil +} diff --git a/storage/pkg/command/users.go b/storage/pkg/command/users.go index d9fc04c4d58..2a8a191b048 100644 --- a/storage/pkg/command/users.go +++ b/storage/pkg/command/users.go @@ -48,11 +48,19 @@ func Users(cfg *config.Config) *cli.Command { pidFile := path.Join(os.TempDir(), "revad-"+c.Command.Name+"-"+uuid.String()+".pid") rcfg := usersConfigFromStruct(c, cfg) + logger.Debug(). Str("server", "users"). Interface("reva-config", rcfg). Msg("config") + if cfg.Reva.Users.Driver == "ldap" { + if err := waitForLDAPCA(logger, &cfg.Reva.LDAP); err != nil { + logger.Error().Err(err).Msg("The configured LDAP CA cert does not exist") + return err + } + } + gr.Add(func() error { runtime.RunWithOptions( rcfg, @@ -120,29 +128,7 @@ func usersConfigFromStruct(c *cli.Context, cfg *config.Config) map[string]interf "json": map[string]interface{}{ "users": cfg.Reva.Users.JSON, }, - "ldap": map[string]interface{}{ - "hostname": cfg.Reva.LDAP.Hostname, - "port": cfg.Reva.LDAP.Port, - "cacert": cfg.Reva.LDAP.CACert, - "insecure": cfg.Reva.LDAP.Insecure, - "base_dn": cfg.Reva.LDAP.BaseDN, - "userfilter": cfg.Reva.LDAP.UserFilter, - "attributefilter": cfg.Reva.LDAP.UserAttributeFilter, - "findfilter": cfg.Reva.LDAP.UserFindFilter, - "groupfilter": cfg.Reva.LDAP.UserGroupFilter, - "bind_username": cfg.Reva.LDAP.BindDN, - "bind_password": cfg.Reva.LDAP.BindPassword, - "idp": cfg.Reva.LDAP.IDP, - "schema": map[string]interface{}{ - "dn": "dn", - "uid": cfg.Reva.LDAP.UserSchema.UID, - "mail": cfg.Reva.LDAP.UserSchema.Mail, - "displayName": cfg.Reva.LDAP.UserSchema.DisplayName, - "cn": cfg.Reva.LDAP.UserSchema.CN, - "uidNumber": cfg.Reva.LDAP.UserSchema.UIDNumber, - "gidNumber": cfg.Reva.LDAP.UserSchema.GIDNumber, - }, - }, + "ldap": ldapConfigFromString(cfg), "rest": map[string]interface{}{ "client_id": cfg.Reva.UserGroupRest.ClientID, "client_secret": cfg.Reva.UserGroupRest.ClientSecret, diff --git a/storage/pkg/config/config.go b/storage/pkg/config/config.go index ee6840d906c..cc0639964c5 100644 --- a/storage/pkg/config/config.go +++ b/storage/pkg/config/config.go @@ -363,25 +363,23 @@ type OIDC struct { // LDAP defines the available ldap configuration. type LDAP struct { - Hostname string `yaml:"hostname"` - Port int `yaml:"port"` - CACert string `yaml:"ca_cert"` - Insecure bool `yaml:"insecure"` - BaseDN string `yaml:"base_dn"` - LoginFilter string `yaml:"login_filter"` - UserFilter string `yaml:"user_filter"` - UserAttributeFilter string `yaml:"user_attribute_filter"` - UserFindFilter string `yaml:"user_find_filter"` - UserGroupFilter string `yaml:"user_group_filter"` - GroupFilter string `yaml:"group_filter"` - GroupAttributeFilter string `yaml:"group_attribute_filter"` - GroupFindFilter string `yaml:"group_finder_filter"` - GroupMemberFilter string `yaml:"group_member_filter"` - BindDN string `yaml:"bind_dn"` - BindPassword string `yaml:"bind_password"` - IDP string `yaml:"idp"` - UserSchema LDAPUserSchema `yaml:"user_schema"` - GroupSchema LDAPGroupSchema `yaml:"group_schema"` + URI string `yaml:"uri"` + CACert string `yaml:"ca_cert"` + Insecure bool `yaml:"insecure"` + UserBaseDN string `yaml:"user_base_dn"` + GroupBaseDN string `yaml:"group_base_dn"` + UserScope string `yaml:"user_scope"` + GroupScope string `yaml:"group_scope"` + UserObjectClass string `yaml:"user_objectclass"` + GroupObjectClass string `yaml:"group_objectclass"` + UserFilter string `yaml:"user_filter"` + GroupFilter string `yaml:"group_filter"` + LoginAttributes []string `yaml:"login_attributes"` + BindDN string `yaml:"bind_dn"` + BindPassword string `yaml:"bind_password"` + IDP string `yaml:"idp"` + UserSchema LDAPUserSchema `yaml:"user_schema"` + GroupSchema LDAPGroupSchema `yaml:"group_schema"` } // UserGroupRest defines the REST driver specification for user and group resolution. @@ -413,21 +411,24 @@ type UserOwnCloudSQL struct { // LDAPUserSchema defines the available ldap user schema configuration. type LDAPUserSchema struct { - UID string `yaml:"uid"` - Mail string `yaml:"mail"` - DisplayName string `yaml:"display_name"` - CN string `yaml:"cn"` - UIDNumber string `yaml:"uid_number"` - GIDNumber string `yaml:"gid_number"` + ID string `yaml:"id"` + IDIsOctetString bool `yaml:"id_is_octet_string"` + Mail string `yaml:"mail"` + DisplayName string `yaml:"display_name"` + Username string `yaml:"user_name"` + UIDNumber string `yaml:"uid_number"` + GIDNumber string `yaml:"gid_number"` } // LDAPGroupSchema defines the available ldap group schema configuration. type LDAPGroupSchema struct { - GID string `yaml:"gid"` - Mail string `yaml:"mail"` - DisplayName string `yaml:"display_name"` - CN string `yaml:"cn"` - GIDNumber string `yaml:"gid_number"` + ID string `yaml:"id"` + IDIsOctetString bool `yaml:"id_is_octet_string"` + Mail string `yaml:"mail"` + DisplayName string `yaml:"display_name"` + Groupname string `yaml:"group_name"` + Member string `yaml:"member"` + GIDNumber string `yaml:"gid_number"` } // OCDav defines the available ocdav configuration. @@ -1020,111 +1021,115 @@ func structMappings(cfg *Config) []shared.EnvBinding { // ldap { - EnvVars: []string{"STORAGE_LDAP_HOSTNAME"}, - Destination: &cfg.Reva.LDAP.Hostname, + EnvVars: []string{"LDAP_URI", "STORAGE_LDAP_URI"}, + Destination: &cfg.Reva.LDAP.URI, }, { - EnvVars: []string{"STORAGE_LDAP_PORT"}, - Destination: &cfg.Reva.LDAP.Port, - }, - { - EnvVars: []string{"STORAGE_LDAP_CACERT"}, + EnvVars: []string{"LDAP_CACERT", "STORAGE_LDAP_CACERT"}, Destination: &cfg.Reva.LDAP.CACert, }, { - EnvVars: []string{"STORAGE_LDAP_INSECURE"}, + EnvVars: []string{"LDAP_INSECURE", "STORAGE_LDAP_INSECURE"}, Destination: &cfg.Reva.LDAP.Insecure, }, { - EnvVars: []string{"STORAGE_LDAP_BASE_DN"}, - Destination: &cfg.Reva.LDAP.BaseDN, + EnvVars: []string{"LDAP_USER_BASE_DN", "STORAGE_LDAP_USER_BASE_DN"}, + Destination: &cfg.Reva.LDAP.UserBaseDN, }, { - EnvVars: []string{"STORAGE_LDAP_LOGINFILTER"}, - Destination: &cfg.Reva.LDAP.LoginFilter, + EnvVars: []string{"LDAP_GROUP_BASE_DN", "STORAGE_LDAP_GROUP_BASE_DN"}, + Destination: &cfg.Reva.LDAP.GroupBaseDN, }, { - EnvVars: []string{"STORAGE_LDAP_USERFILTER"}, - Destination: &cfg.Reva.LDAP.UserFilter, + EnvVars: []string{"LDAP_USER_SCOPE", "STORAGE_LDAP_USER_SCOPE"}, + Destination: &cfg.Reva.LDAP.UserScope, }, { - EnvVars: []string{"STORAGE_LDAP_USERATTRIBUTEFILTER"}, - Destination: &cfg.Reva.LDAP.UserAttributeFilter, + EnvVars: []string{"LDAP_GROUP_SCOPE", "STORAGE_LDAP_GROUP_SCOPE"}, + Destination: &cfg.Reva.LDAP.GroupScope, }, { - EnvVars: []string{"STORAGE_LDAP_USERFINDFILTER"}, - Destination: &cfg.Reva.LDAP.UserFindFilter, + EnvVars: []string{"LDAP_USER_OBJECTCLASS", "STORAGE_LDAP_USER_OBJECTCLASS"}, + Destination: &cfg.Reva.LDAP.UserObjectClass, }, { - EnvVars: []string{"STORAGE_LDAP_USERGROUPFILTER"}, - Destination: &cfg.Reva.LDAP.UserGroupFilter, + EnvVars: []string{"LDAP_GROUP_OBJECTCLASS", "STORAGE_LDAP_GROUP_OBJECTCLASS"}, + Destination: &cfg.Reva.LDAP.GroupObjectClass, }, { - EnvVars: []string{"STORAGE_LDAP_GROUPFILTER"}, - Destination: &cfg.Reva.LDAP.GroupFilter, + EnvVars: []string{"LDAP_LOGIN_ATTRIBUTES", "STORAGE_LDAP_LOGIN_ATTRIBUTES"}, + Destination: &cfg.Reva.LDAP.LoginAttributes, }, { - EnvVars: []string{"STORAGE_LDAP_GROUPATTRIBUTEFILTER"}, - Destination: &cfg.Reva.LDAP.GroupAttributeFilter, - }, - { - EnvVars: []string{"STORAGE_LDAP_GROUPFINDFILTER"}, - Destination: &cfg.Reva.LDAP.GroupFindFilter, + EnvVars: []string{"LDAP_USERFILTER", "STORAGE_LDAP_USERFILTER"}, + Destination: &cfg.Reva.LDAP.UserFilter, }, { - EnvVars: []string{"STORAGE_LDAP_GROUPMEMBERFILTER"}, - Destination: &cfg.Reva.LDAP.GroupMemberFilter, + EnvVars: []string{"LDAP_GROUPFILTER", "STORAGE_LDAP_GROUPFILTER"}, + Destination: &cfg.Reva.LDAP.GroupFilter, }, { - EnvVars: []string{"STORAGE_LDAP_BIND_DN"}, + EnvVars: []string{"LDAP_BIND_DN", "STORAGE_LDAP_BIND_DN"}, Destination: &cfg.Reva.LDAP.BindDN, }, { - EnvVars: []string{"STORAGE_LDAP_BIND_PASSWORD"}, + EnvVars: []string{"LDAP_BIND_PASSWORD", "STORAGE_LDAP_BIND_PASSWORD"}, Destination: &cfg.Reva.LDAP.BindPassword, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_UID"}, - Destination: &cfg.Reva.LDAP.UserSchema.UID, + EnvVars: []string{"LDAP_USER_SCHEMA_ID", "STORAGE_LDAP_USER_SCHEMA_ID"}, + Destination: &cfg.Reva.LDAP.UserSchema.ID, + }, + { + EnvVars: []string{"LDAP_USER_SCHEMA_ID_IS_OCTETSTRING", "STORAGE_LDAP_USER_SCHEMA_ID_IS_OCTETSTRING"}, + Destination: &cfg.Reva.LDAP.UserSchema.IDIsOctetString, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_MAIL"}, + EnvVars: []string{"LDAP_USER_SCHEMA_MAIL", "STORAGE_LDAP_USER_SCHEMA_MAIL"}, Destination: &cfg.Reva.LDAP.UserSchema.Mail, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_DISPLAYNAME"}, + EnvVars: []string{"LDAP_USER_SCHEMA_DISPLAYNAME", "STORAGE_LDAP_USER_SCHEMA_DISPLAYNAME"}, Destination: &cfg.Reva.LDAP.UserSchema.DisplayName, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_CN"}, - Destination: &cfg.Reva.LDAP.UserSchema.CN, + EnvVars: []string{"LDAP_USER_SCHEMA_USERNAME", "STORAGE_LDAP_USER_SCHEMA_USERNAME"}, + Destination: &cfg.Reva.LDAP.UserSchema.Username, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_UID_NUMBER"}, + EnvVars: []string{"LDAP_USER_SCHEMA_UID_NUMBER", "STORAGE_LDAP_USER_SCHEMA_UID_NUMBER"}, Destination: &cfg.Reva.LDAP.UserSchema.UIDNumber, }, { - EnvVars: []string{"STORAGE_LDAP_USER_SCHEMA_GID_NUMBER"}, + EnvVars: []string{"LDAP_USER_SCHEMA_GID_NUMBER", "STORAGE_LDAP_USER_SCHEMA_GID_NUMBER"}, Destination: &cfg.Reva.LDAP.UserSchema.GIDNumber, }, { - EnvVars: []string{"STORAGE_LDAP_GROUP_SCHEMA_GID"}, - Destination: &cfg.Reva.LDAP.GroupSchema.GID, + EnvVars: []string{"LDAP_GROUP_SCHEMA_ID", "STORAGE_LDAP_GROUP_SCHEMA_ID"}, + Destination: &cfg.Reva.LDAP.GroupSchema.ID, }, { - EnvVars: []string{"STORAGE_LDAP_GROUP_SCHEMA_MAIL"}, + EnvVars: []string{"LDAP_GROUP_SCHEMA_ID_IS_OCTETSTRING", "STORAGE_LDAP_GROUP_SCHEMA_ID_IS_OCTETSTRING"}, + Destination: &cfg.Reva.LDAP.UserSchema.IDIsOctetString, + }, + { + EnvVars: []string{"LDAP_GROUP_SCHEMA_MAIL", "STORAGE_LDAP_GROUP_SCHEMA_MAIL"}, Destination: &cfg.Reva.LDAP.GroupSchema.Mail, }, { - EnvVars: []string{"STORAGE_LDAP_GROUP_SCHEMA_DISPLAYNAME"}, + EnvVars: []string{"LDAP_GROUP_SCHEMA_DISPLAYNAME", "STORAGE_LDAP_GROUP_SCHEMA_DISPLAYNAME"}, Destination: &cfg.Reva.LDAP.GroupSchema.DisplayName, }, { - EnvVars: []string{"STORAGE_LDAP_GROUP_SCHEMA_CN"}, - Destination: &cfg.Reva.LDAP.GroupSchema.CN, + EnvVars: []string{"LDAP_GROUP_SCHEMA_GROUPNAME", "STORAGE_LDAP_GROUP_SCHEMA_GROUPNAME"}, + Destination: &cfg.Reva.LDAP.GroupSchema.Groupname, + }, + { + EnvVars: []string{"LDAP_GROUP_SCHEMA_MEMBER", "STORAGE_LDAP_GROUP_SCHEMA_MEMBER"}, + Destination: &cfg.Reva.LDAP.GroupSchema.Member, }, { - EnvVars: []string{"STORAGE_LDAP_GROUP_SCHEMA_GID_NUMBER"}, + EnvVars: []string{"LDAP_GROUP_SCHEMA_GID_NUMBER", "STORAGE_LDAP_GROUP_SCHEMA_GID_NUMBER"}, Destination: &cfg.Reva.LDAP.GroupSchema.GIDNumber, }, diff --git a/storage/pkg/config/defaults/defaultconfig.go b/storage/pkg/config/defaults/defaultconfig.go index 20847394962..cdf9741dcf0 100644 --- a/storage/pkg/config/defaults/defaultconfig.go +++ b/storage/pkg/config/defaults/defaultconfig.go @@ -44,36 +44,35 @@ func DefaultConfig() *config.Config { IDClaim: "preferred_username", }, LDAP: config.LDAP{ - Hostname: "localhost", - Port: 9126, - CACert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"), - Insecure: false, - BaseDN: "dc=ocis,dc=test", - LoginFilter: "(&(objectclass=posixAccount)(|(cn={{login}})(mail={{login}})))", - UserFilter: "(&(objectclass=posixAccount)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", - UserAttributeFilter: "(&(objectclass=posixAccount)({{attr}}={{value}}))", - UserFindFilter: "(&(objectclass=posixAccount)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", - UserGroupFilter: "(&(objectclass=posixGroup)(cn={{query}}*))", - GroupFilter: "(&(objectclass=posixGroup)(|(ownclouduuid={{.OpaqueId}})(cn={{.OpaqueId}})))", - GroupAttributeFilter: "(&(objectclass=posixGroup)({{attr}}={{value}}))", - GroupFindFilter: "(&(objectclass=posixGroup)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))", - GroupMemberFilter: "(&(objectclass=posixAccount)(ownclouduuid={{.OpaqueId}}*))", - BindDN: "cn=reva,ou=sysusers,dc=ocis,dc=test", - BindPassword: "reva", - IDP: defaultPublicURL, + URI: "ldaps://localhost:9126", + CACert: path.Join(defaults.BaseDataPath(), "ldap", "ldap.crt"), + Insecure: false, + UserBaseDN: "dc=ocis,dc=test", + GroupBaseDN: "dc=ocis,dc=test", + UserScope: "sub", + GroupScope: "sub", + LoginAttributes: []string{"cn", "mail"}, + UserFilter: "", + GroupFilter: "", + UserObjectClass: "posixAccount", + GroupObjectClass: "posixGroup", + BindDN: "cn=reva,ou=sysusers,dc=ocis,dc=test", + BindPassword: "reva", + IDP: defaultPublicURL, UserSchema: config.LDAPUserSchema{ - UID: "ownclouduuid", + ID: "ownclouduuid", Mail: "mail", DisplayName: "displayname", - CN: "cn", + Username: "cn", UIDNumber: "uidnumber", GIDNumber: "gidnumber", }, GroupSchema: config.LDAPGroupSchema{ - GID: "cn", + ID: "cn", Mail: "mail", DisplayName: "cn", - CN: "cn", + Groupname: "cn", + Member: "cn", GIDNumber: "gidnumber", }, },