diff --git a/.drone.star b/.drone.star index 3607328fe63..a2e0bc46e80 100644 --- a/.drone.star +++ b/.drone.star @@ -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", diff --git a/changelog/unreleased/ldap-config.md b/changelog/unreleased/ldap-config.md new file mode 100644 index 00000000000..7055620133a --- /dev/null +++ b/changelog/unreleased/ldap-config.md @@ -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 diff --git a/changelog/unreleased/update-reva.md b/changelog/unreleased/update-reva.md index bf930d44a39..08809c020a2 100644 --- a/changelog/unreleased/update-reva.md +++ b/changelog/unreleased/update-reva.md @@ -5,5 +5,7 @@ Updated reva to version 2.x.x. This update includes: * TODO https://github.com/owncloud/ocis/pull/3430 +https://github.com/owncloud/ocis/pull/3476 https://github.com/owncloud/ocis/pull/3482 https://github.com/owncloud/ocis/pull/3497 + diff --git a/deployments/examples/oc10_ocis_parallel/docker-compose.yml b/deployments/examples/oc10_ocis_parallel/docker-compose.yml index cb4a503437d..4538ba147d4 100644 --- a/deployments/examples/oc10_ocis_parallel/docker-compose.yml +++ b/deployments/examples/oc10_ocis_parallel/docker-compose.yml @@ -58,8 +58,7 @@ services: STORAGE_LDAP_IDP: https://${KEYCLOAK_DOMAIN:-keycloak.owncloud.test}/auth/realms/${KEYCLOAK_REALM:-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: ${LDAP_ADMIN_PASSWORD:-admin} @@ -68,25 +67,22 @@ services: 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: "dc=owncloud,dc=com" 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_GROUP_OBJECTCLASS: "groupOfUniqueNames" + STORAGE_LDAP_GROUPFILTER: "(objectclass=owncloud)" + STORAGE_LDAP_USER_BASE_DN: "dc=owncloud,dc=com" + 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_USERS_DRIVER: owncloudsql STORAGE_METADATA_DRIVER: ocis # keep metadata on ocis storage since this are only small files atm diff --git a/deployments/examples/ocis_individual_services/docker-compose.yml b/deployments/examples/ocis_individual_services/docker-compose.yml index bdf844a7e22..2af750b9a97 100644 --- a/deployments/examples/ocis_individual_services/docker-compose.yml +++ b/deployments/examples/ocis_individual_services/docker-compose.yml @@ -608,8 +608,7 @@ services: STORAGE_USERPROVIDER_ADDR: 0.0.0.0:9144 STORAGE_USERPROVIDER_DRIVER: ldap - STORAGE_LDAP_HOSTNAME: glauth - STORAGE_LDAP_PORT: 9126 + STORAGE_LDAP_URI: "ldaps://glauth:9126" STORAGE_LDAP_INSECURE: "true" STORAGE_LDAP_BIND_PASSWORD: ${STORAGE_LDAP_BIND_PASSWORD:-reva} STORAGE_LDAP_IDP: https://${OCIS_DOMAIN:-ocis.owncloud.test} @@ -639,8 +638,7 @@ services: STORAGE_GROUPPROVIDER_ADDR: 0.0.0.0:9160 STORAGE_GROUPPROVIDER_DRIVER: ldap - STORAGE_LDAP_HOSTNAME: glauth - STORAGE_LDAP_PORT: 9126 + STORAGE_LDAP_URI: "ldaps://glauth:9126" STORAGE_LDAP_INSECURE: "true" STORAGE_LDAP_BIND_PASSWORD: ${STORAGE_LDAP_BIND_PASSWORD:-reva} STORAGE_LDAP_IDP: https://${OCIS_DOMAIN:-ocis.owncloud.test} diff --git a/deployments/examples/ocis_ldap/docker-compose.yml b/deployments/examples/ocis_ldap/docker-compose.yml index 18504d8e21b..b5547a8b201 100644 --- a/deployments/examples/ocis_ldap/docker-compose.yml +++ b/deployments/examples/ocis_ldap/docker-compose.yml @@ -53,26 +53,21 @@ services: - /entrypoint-override.sh environment: # CS3 users from ldap specific configuration - IDP_LDAP_FILTER: "(&(objectclass=inetOrgPerson)(objectClass=owncloud))" - IDP_LDAP_URI: ldap://ldap-server:389 - IDP_LDAP_BIND_DN: "cn=admin,dc=owncloud,dc=com" - IDP_LDAP_BIND_PASSWORD: ${LDAP_ADMIN_PASSWORD:-admin} - IDP_LDAP_BASE_DN: "dc=owncloud,dc=com" - IDP_LDAP_LOGIN_ATTRIBUTE: uid + LDAP_URI: ldaps://ldap-server + LDAP_INSECURE: "true" + LDAP_BIND_DN: "cn=admin,dc=owncloud,dc=com" + LDAP_BIND_PASSWORD: ${LDAP_ADMIN_PASSWORD:-admin} + LDAP_GROUP_BASE_DN: "dc=owncloud,dc=com" + LDAP_GROUPFILTER: "(objectclass=owncloud)" + LDAP_GROUP_OBJECTCLASS: "groupOfUniqueNames" + LDAP_USER_BASE_DN: "dc=owncloud,dc=com" + LDAP_USERFILTER: "(objectclass=owncloud)" + LDAP_USER_OBEJECTCLASS: "inetOrgPerson" + LDAP_LOGIN_ATTRIBUTES: "uid,mail" + IDP_LDAP_LOGIN_ATTRIBUTE: "uid" IDP_LDAP_UUID_ATTRIBUTE: "ownclouduuid" IDP_LDAP_UUID_ATTRIBUTE_TYPE: binary PROXY_ACCOUNT_BACKEND_TYPE: cs3 - STORAGE_LDAP_HOSTNAME: ldap-server - STORAGE_LDAP_PORT: 636 - STORAGE_LDAP_INSECURE: "true" - STORAGE_LDAP_BASE_DN: "dc=owncloud,dc=com" - STORAGE_LDAP_BIND_DN: "cn=admin,dc=owncloud,dc=com" - STORAGE_LDAP_BIND_PASSWORD: ${LDAP_ADMIN_PASSWORD:-admin} - STORAGE_LDAP_LOGINFILTER: '(&(objectclass=inetOrgPerson)(objectclass=owncloud)(|(uid={{login}})(mail={{login}})))' - STORAGE_LDAP_USERFILTER: '(&(objectclass=inetOrgPerson)(objectclass=owncloud)(|(ownclouduuid={{.OpaqueId}})(uid={{.OpaqueId}})))' - STORAGE_LDAP_ATTRIBUTEFILTER: '(&(objectclass=owncloud)({{attr}}={{value}}))' - STORAGE_LDAP_FINDFILTER: '(&(objectclass=owncloud)(|(uid={{query}}*)(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)(description={{query}}*)))' - STORAGE_LDAP_GROUPFILTER: '(&(objectclass=groupOfUniqueNames)(objectclass=owncloud)(ownclouduuid={{.OpaqueId}}*))' # web ui WEB_UI_CONFIG: "/var/tmp/ocis/.config/web-config.json" # General oCIS config diff --git a/go.mod b/go.mod index 64adb1d129e..14c0c3a790e 100644 --- a/go.mod +++ b/go.mod @@ -22,7 +22,7 @@ require ( github.com/blevesearch/bleve/v2 v2.3.2 github.com/coreos/go-oidc/v3 v3.1.0 github.com/cs3org/go-cs3apis v0.0.0-20220328105952-297bef33e13f - github.com/cs3org/reva/v2 v2.0.0-20220408142652-148b87297214 + github.com/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f github.com/disintegration/imaging v1.6.2 github.com/glauth/glauth/v2 v2.0.0-20211021011345-ef3151c28733 github.com/go-chi/chi/v5 v5.0.7 @@ -52,6 +52,7 @@ require ( github.com/oklog/run v1.1.0 github.com/olekukonko/tablewriter v0.0.5 github.com/onsi/ginkgo v1.16.5 + github.com/onsi/ginkgo/v2 v2.1.3 github.com/onsi/gomega v1.19.0 github.com/owncloud/libre-graph-api-go v0.13.3 github.com/pkg/errors v0.9.1 diff --git a/go.sum b/go.sum index df9a90baf58..857c2122737 100644 --- a/go.sum +++ b/go.sum @@ -335,8 +335,8 @@ 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/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f h1:SNQSbtvhsQ6KvdDJlW536pUMq8RzghQMDCkYYKEFn8c= +github.com/cs3org/reva/v2 v2.0.0-20220411161034-134ed5a0801f/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= diff --git a/graph/pkg/config/config.go b/graph/pkg/config/config.go index fe59ea6901d..4d11d73f93e 100644 --- a/graph/pkg/config/config.go +++ b/graph/pkg/config/config.go @@ -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 { diff --git a/graph/pkg/config/defaults/defaultconfig.go b/graph/pkg/config/defaults/defaultconfig.go index 5bab47e892b..7ea8774cf03 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/ocis-pkg/config/config_suite_test.go b/ocis-pkg/config/config_suite_test.go new file mode 100644 index 00000000000..c6e29ba7169 --- /dev/null +++ b/ocis-pkg/config/config_suite_test.go @@ -0,0 +1,13 @@ +package config_test + +import ( + "testing" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +func TestConfig(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Config Suite") +} diff --git a/ocis-pkg/config/config_test.go b/ocis-pkg/config/config_test.go index 6a77d3cda97..bfbc7b40873 100644 --- a/ocis-pkg/config/config_test.go +++ b/ocis-pkg/config/config_test.go @@ -1,17 +1,16 @@ -package config +package config_test import ( - "fmt" - "testing" - + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + "github.com/owncloud/ocis/ocis-pkg/config" "gopkg.in/yaml.v2" ) -func TestDefaultConfig(t *testing.T) { - cfg := DefaultConfig() - yBytes, err := yaml.Marshal(cfg) - if err != nil { - panic(err) - } - fmt.Println(string(yBytes)) -} +var _ = Describe("Config", func() { + It("Success generating the default config", func() { + cfg := config.DefaultConfig() + _, err := yaml.Marshal(cfg) + Expect(err).To(BeNil()) + }) +}) diff --git a/ocis-pkg/config/environment.go b/ocis-pkg/config/environment.go index c713d92e40c..d30c2642284 100644 --- a/ocis-pkg/config/environment.go +++ b/ocis-pkg/config/environment.go @@ -3,6 +3,7 @@ package config import ( "fmt" "reflect" + "strings" gofig "github.com/gookit/config/v2" "github.com/owncloud/ocis/ocis-pkg/shared" @@ -35,6 +36,11 @@ func bindEnv(c *gofig.Config, bindings []shared.EnvBinding) error { // defaults to float64 r := c.Float(bindings[i].EnvVars[j]) *bindings[i].Destination.(*float64) = r + case "*[]string": + // Treat values a comma-separated list + r := c.String(bindings[i].EnvVars[j]) + vals := envStringToSlice(r) + *bindings[i].Destination.(*[]string) = vals default: // it is unlikely we will ever get here. Let this serve more as a runtime check for when debugging. return fmt.Errorf("invalid type for env var: `%v`", bindings[i].EnvVars[j]) @@ -45,3 +51,11 @@ func bindEnv(c *gofig.Config, bindings []shared.EnvBinding) error { return nil } + +func envStringToSlice(value string) []string { + vals := strings.Split(value, ",") + for i := range vals { + vals[i] = strings.TrimSpace(vals[i]) + } + return vals +} diff --git a/ocis-pkg/config/environment_test.go b/ocis-pkg/config/environment_test.go new file mode 100644 index 00000000000..32a22ef1f32 --- /dev/null +++ b/ocis-pkg/config/environment_test.go @@ -0,0 +1,35 @@ +package config_test + +import ( + gofig "github.com/gookit/config/v2" + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + ociscfg "github.com/owncloud/ocis/ocis-pkg/config" + "github.com/owncloud/ocis/ocis-pkg/shared" +) + +var _ = Describe("Environment", func() { + It("Succeed to parse a comma separated list in to a sting slice", func() { + cfg := gofig.NewEmpty("test") + err := cfg.Set("stringlist", "one,two,three") + Expect(err).To(Not(HaveOccurred())) + err = cfg.Set("stringlist2", "one ,two , t h r e e") + Expect(err).To(Not(HaveOccurred())) + var stringTest, stringTest2 []string + eb := []shared.EnvBinding{ + { + EnvVars: []string{"stringlist"}, + Destination: &stringTest, + }, + { + EnvVars: []string{"stringlist2"}, + Destination: &stringTest2, + }, + } + err = ociscfg.BindEnv(cfg, eb) + Expect(err).To(Not(HaveOccurred())) + Expect(stringTest).To(Equal([]string{"one", "two", "three"})) + Expect(stringTest2).To(Equal([]string{"one", "two", "t h r e e"})) + + }) +}) 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..599d955cca7 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.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{"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", }, }, diff --git a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md index e000b1dccb5..bc60e4d2ca8 100644 --- a/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md +++ b/tests/acceptance/expected-failures-webUI-on-OCIS-storage.md @@ -350,7 +350,6 @@ Other free text and markdown formatting can be used elsewhere in the document if - [webUITags/createTags.feature:79](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUITags/createTags.feature#L79) ### [When a user shares folder to a group, the sharer is shown as group in group member's sharing-sidebar](https://github.com/owncloud/web/issues/5216) - - [webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature:41](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature#L41) - [webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature:42](https://github.com/owncloud/web/blob/master/tests/acceptance/features/webUISharingInternalGroupsEdgeCases/shareWithGroupsEdgeCases.feature#L42) ### [impossible to navigate into a folder in the trashbin](https://github.com/owncloud/web/issues/1725)