Unify LDAP config settings accross services

This adapts the storage service to the recent changes of the LDAP
settings in reva.

Also we define a new set of LDAP env variables that can be shared
between all LDAP related ocis services (graph, idp, storage-auth-basic,
storage-userprovider, storage-groupprovider, idm). This should simplify
the most LDAP based configurations considerably.
This commit is contained in:
Ralf Haferkamp
2022-04-06 17:46:38 +02:00
parent b0fb996b82
commit dc6a4fdc02
15 changed files with 296 additions and 220 deletions
+12 -14
View File
@@ -1642,8 +1642,7 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"STORAGE_LDAP_IDP": "https://keycloak/auth/realms/owncloud",
"WEB_OIDC_SCOPE": "openid profile email owncloud",
# LDAP bind
"STORAGE_LDAP_HOSTNAME": "openldap",
"STORAGE_LDAP_PORT": 636,
"STORAGE_LDAP_URI": "ldaps://openldap",
"STORAGE_LDAP_INSECURE": "true",
"STORAGE_LDAP_BIND_DN": "cn=admin,dc=owncloud,dc=com",
"STORAGE_LDAP_BIND_PASSWORD": "admin",
@@ -1652,25 +1651,24 @@ def ocisServer(storage, accounts_hash_difficulty = 4, volumes = [], depends_on =
"PROXY_ACCOUNT_BACKEND_TYPE": "cs3", # proxy should get users from CS3APIS (which gets it from LDAP)
"PROXY_USER_OIDC_CLAIM": "ocis.user.uuid", # claim was added in Keycloak
"PROXY_USER_CS3_CLAIM": "userid", # equals STORAGE_LDAP_USER_SCHEMA_UID
"STORAGE_LDAP_BASE_DN": "dc=owncloud,dc=com",
"STORAGE_LDAP_GROUP_BASE_DN": "ou=testgroups,dc=owncloud,dc=com",
"STORAGE_LDAP_GROUP_OBJECTCLASS": "groupOfUniqueNames",
"STORAGE_LDAP_GROUPFILTER": "(objectclass=owncloud)",
"STORAGE_LDAP_GROUP_SCHEMA_DISPLAYNAME": "cn",
"STORAGE_LDAP_GROUP_SCHEMA_GID_NUMBER": "gidnumber",
"STORAGE_LDAP_GROUP_SCHEMA_GID": "cn",
"STORAGE_LDAP_GROUP_SCHEMA_ID": "cn",
"STORAGE_LDAP_GROUP_SCHEMA_MAIL": "mail",
"STORAGE_LDAP_GROUPATTRIBUTEFILTER": "(&(objectclass=posixGroup)(objectclass=owncloud)({{attr}}={{value}}))",
"STORAGE_LDAP_GROUPFILTER": "(&(objectclass=groupOfUniqueNames)(objectclass=owncloud)(ownclouduuid={{.OpaqueId}}*))",
"STORAGE_LDAP_GROUPMEMBERFILTER": "(&(objectclass=posixAccount)(objectclass=owncloud)(ownclouduuid={{.OpaqueId}}*))",
"STORAGE_LDAP_USERGROUPFILTER": "(&(objectclass=posixGroup)(objectclass=owncloud)(ownclouduuid={{.OpaqueId}}*))",
"STORAGE_LDAP_USER_SCHEMA_CN": "cn",
"STORAGE_LDAP_GROUP_SCHEMA_MEMBER": "cn",
"STORAGE_LDAP_USER_BASE_DN": "ou=testusers,dc=owncloud,dc=com",
"STORAGE_LDAP_USER_OBJECTCLASS": "posixAccount",
"STORAGE_LDAP_USERFILTER": "(objectclass=owncloud)",
"STORAGE_LDAP_USER_SCHEMA_USERNAME": "cn",
"STORAGE_LDAP_USER_SCHEMA_DISPLAYNAME": "displayname",
"STORAGE_LDAP_USER_SCHEMA_GID_NUMBER": "gidnumber",
"STORAGE_LDAP_USER_SCHEMA_MAIL": "mail",
"STORAGE_LDAP_USER_SCHEMA_UID_NUMBER": "uidnumber",
"STORAGE_LDAP_USER_SCHEMA_UID": "ownclouduuid",
"STORAGE_LDAP_LOGINFILTER": "(&(objectclass=posixAccount)(objectclass=owncloud)(|(uid={{login}})(mail={{login}})))",
"STORAGE_LDAP_USERATTRIBUTEFILTER": "(&(objectclass=posixAccount)(objectclass=owncloud)({{attr}}={{value}}))",
"STORAGE_LDAP_USERFILTER": "(&(objectclass=posixAccount)(objectclass=owncloud)(|(ownclouduuid={{.OpaqueId}})(uid={{.OpaqueId}})))",
"STORAGE_LDAP_USERFINDFILTER": "(&(objectclass=posixAccount)(objectclass=owncloud)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)))",
"STORAGE_LDAP_USER_SCHEMA_ID": "ownclouduuid",
"STORAGE_LDAP_LOGIN_ATTRIBUTES": "uid,mail",
# ownCloudSQL storage driver
"STORAGE_HOME_DRIVER": "owncloudsql",
"STORAGE_USERS_DRIVER": "owncloudsql",
+39
View File
@@ -0,0 +1,39 @@
Enhancement: Unify LDAP config settings accross services
The storage services where updated to adapt for the recent changes of the LDAP
settings in reva.
Also we allow now to use a new set of top-level LDAP environment variables that
are shared between all LDAP-using services in ocis (graph, idp,
storage-auth-basic, storage-userprovider, storage-groupprovider, idm). This
should simplify the most LDAP based configurations considerably.
Here is a list of the new environment variables:
LDAP_URI
LDAP_INSECURE
LDAP_CACERT
LDAP_BIND_DN
LDAP_BIND_PASSWORD
LDAP_LOGIN_ATTRIBUTES
LDAP_USER_BASE_DN
LDAP_USER_SCOPE
LDAP_USER_FILTER
LDAP_USER_OBJECTCLASS
LDAP_USER_SCHEMA_MAIL
LDAP_USER_SCHEMA_DISPLAY_NAME
LDAP_USER_SCHEMA_USERNAME
LDAP_USER_SCHEMA_ID
LDAP_USER_SCHEMA_ID_IS_OCTETSTRING
LDAP_GROUP_BASE_DN
LDAP_GROUP_SCOPE
LDAP_GROUP_FILTER
LDAP_GROUP_OBJECTCLASS
LDAP_GROUP_SCHEMA_GROUPNAME
LDAP_GROUP_SCHEMA_ID
LDAP_GROUP_SCHEMA_ID_IS_OCTETSTRING
Where need these can be overwritten by service specific variables. E.g. it is possible
to use STORAGE_LDAP_URI to overide the top-level LDAP_URI variable.
https://github.com/owncloud/ocis/pull/3476
https://github.com/owncloud/ocis/issues/3150
+2 -2
View File
@@ -335,8 +335,6 @@ github.com/crewjam/httperr v0.2.0/go.mod h1:Jlz+Sg/XqBQhyMjdDiC+GNNRzZTD7x39Gu3p
github.com/crewjam/saml v0.4.6 h1:XCUFPkQSJLvzyl4cW9OvpWUbRf0gE7VUpU8ZnilbeM4=
github.com/crewjam/saml v0.4.6/go.mod h1:ZBOXnNPFzB3CgOkRm7Nd6IVdkG+l/wF+0ZXLqD96t1A=
github.com/cs3org/cato v0.0.0-20200828125504-e418fc54dd5e/go.mod h1:XJEZ3/EQuI3BXTp/6DUzFr850vlxq11I6satRtz0YQ4=
github.com/cs3org/reva/v2 v2.0.0-20220408142652-148b87297214 h1:8Akb8HGdilByInCNDEzwo2TSRTd7JNcHjU73Y3f6Yuo=
github.com/cs3org/reva/v2 v2.0.0-20220408142652-148b87297214/go.mod h1:rE2wCGoiGiUuQ3zj6aD7sZ+BhboLyNsNQ3z3auunWm4=
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=
@@ -1219,6 +1217,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-20220407163203-9c01a18d0d08 h1:78yYZJkoSr5v/zA2ARh/YSbHqBLWSwaNFirR1rQDVIs=
github.com/rhafer/reva/v2 v2.0.0-20220407163203-9c01a18d0d08/go.mod h1:rE2wCGoiGiUuQ3zj6aD7sZ+BhboLyNsNQ3z3auunWm4=
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=
+17 -15
View File
@@ -37,26 +37,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 {
+4 -2
View File
@@ -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",
},
+9 -5
View File
@@ -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)(<filter_from_args>))"
// resulting in a filter like "(&(LDAP.groupFilter)(objectClass=LDAP.groupObjectClass)(<filter_from_args>))"
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(
+10 -9
View File
@@ -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.
+3 -2
View File
@@ -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",
},
}
}
+5 -1
View File
@@ -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 {
+8 -19
View File
@@ -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,
+8 -22
View File
@@ -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,
+60
View File
@@ -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
}
+9 -23
View File
@@ -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,
+90 -85
View File
@@ -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"},
EnvVars: []string{"LDAP_USER_SCOPE", "STORAGE_LDAP_USER_SCOPE"},
Destination: &cfg.Reva.LDAP.UserScope,
},
{
EnvVars: []string{"LDAP_GROUP_SCOPE", "STORAGE_LDAP_GROUP_SCOPE"},
Destination: &cfg.Reva.LDAP.GroupScope,
},
{
EnvVars: []string{"LDAP_USER_OBJECTCLASS", "STORAGE_LDAP_USER_OBJECTCLASS"},
Destination: &cfg.Reva.LDAP.UserObjectClass,
},
{
EnvVars: []string{"LDAP_GROUP_OBJECTCLASS", "STORAGE_LDAP_GROUP_OBJECTCLASS"},
Destination: &cfg.Reva.LDAP.GroupObjectClass,
},
{
EnvVars: []string{"LDAP_LOGIN_ATTRIBUTES", "STORAGE_LDAP_LOGIN_ATTRIBUTES"},
Destination: &cfg.Reva.LDAP.LoginAttributes,
},
{
EnvVars: []string{"LDAP_USERFILTER", "STORAGE_LDAP_USERFILTER"},
Destination: &cfg.Reva.LDAP.UserFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_USERATTRIBUTEFILTER"},
Destination: &cfg.Reva.LDAP.UserAttributeFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_USERFINDFILTER"},
Destination: &cfg.Reva.LDAP.UserFindFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_USERGROUPFILTER"},
Destination: &cfg.Reva.LDAP.UserGroupFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_GROUPFILTER"},
EnvVars: []string{"LDAP_GROUPFILTER", "STORAGE_LDAP_GROUPFILTER"},
Destination: &cfg.Reva.LDAP.GroupFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_GROUPATTRIBUTEFILTER"},
Destination: &cfg.Reva.LDAP.GroupAttributeFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_GROUPFINDFILTER"},
Destination: &cfg.Reva.LDAP.GroupFindFilter,
},
{
EnvVars: []string{"STORAGE_LDAP_GROUPMEMBERFILTER"},
Destination: &cfg.Reva.LDAP.GroupMemberFilter,
},
{
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{"STORAGE_LDAP_USER_SCHEMA_MAIL"},
EnvVars: []string{"LDAP_USER_SCHEMA_ID_IS_OCTETSTRING", "STORAGE_LDAP_USER_SCHEMA_ID_IS_OCTETSTRING"},
Destination: &cfg.Reva.LDAP.UserSchema.IDIsOctetString,
},
{
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.GroupSchema.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{"STORAGE_LDAP_GROUP_SCHEMA_GID_NUMBER"},
EnvVars: []string{"LDAP_GROUP_SCHEMA_MEMBER", "STORAGE_LDAP_GROUP_SCHEMA_MEMBER"},
Destination: &cfg.Reva.LDAP.GroupSchema.Member,
},
{
EnvVars: []string{"LDAP_GROUP_SCHEMA_GID_NUMBER", "STORAGE_LDAP_GROUP_SCHEMA_GID_NUMBER"},
Destination: &cfg.Reva.LDAP.GroupSchema.GIDNumber,
},
+20 -21
View File
@@ -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",
},
},