From 98ff36773a5159106a21f016413efe63b81cb94a Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 23 Feb 2022 14:32:59 +0100 Subject: [PATCH 1/3] Allow to run user_provider integration test with LDAP driver The test are skipped by default for now, as they require an LDAP Server to be setup. To run you can e.g. use OpenLDAP in docker use e.g.: ``` docker run --name openldap \ --volume ./tests/integration/grpc/fixtures/ldap/:/container/service/slapd/assets/config/bootstrap/ldif/custom \ -e LDAP_DOMAIN="owncloud.com" \ -e LDAP_TLS_VERIFY_CLIENT=never \ -e LDAP_ORGANISATION=ownCloud \ -e LDAP_ADMIN_PASSWORD=admin \ -e LDAP_REMOVE_CONFIG_AFTER_SETUP=false \ osixia/openldap ``` run the test suite with: ``` cd tests/integration/ RUN_LDAP_TESTS=1 ~/go/bin/ginkgo [--focus "ldap"] ./... ``` --- .../unreleased/ldap-integration-tests.md | 6 ++ .../fixtures/ldap/10_owncloud_schema.ldif | 9 ++ .../grpc/fixtures/ldap/20_users.ldif | 84 +++++++++++++++++++ .../grpc/fixtures/ldap/30_groups_rfc2307.ldif | 75 +++++++++++++++++ .../grpc/fixtures/userprovider-ldap.toml | 25 ++++++ tests/integration/grpc/userprovider_test.go | 18 ++++ 6 files changed, 217 insertions(+) create mode 100644 changelog/unreleased/ldap-integration-tests.md create mode 100644 tests/integration/grpc/fixtures/ldap/10_owncloud_schema.ldif create mode 100644 tests/integration/grpc/fixtures/ldap/20_users.ldif create mode 100644 tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif create mode 100644 tests/integration/grpc/fixtures/userprovider-ldap.toml diff --git a/changelog/unreleased/ldap-integration-tests.md b/changelog/unreleased/ldap-integration-tests.md new file mode 100644 index 0000000000..a7ab749a35 --- /dev/null +++ b/changelog/unreleased/ldap-integration-tests.md @@ -0,0 +1,6 @@ +Enhancement: Allow running userprovider integration tests for the LDAP driver + +We extended the integration test suite for the userprovider to allow running it +with an LDAP server. + +https://github.com/cs3org/reva/pull/2584 diff --git a/tests/integration/grpc/fixtures/ldap/10_owncloud_schema.ldif b/tests/integration/grpc/fixtures/ldap/10_owncloud_schema.ldif new file mode 100644 index 0000000000..3aec8f8e1a --- /dev/null +++ b/tests/integration/grpc/fixtures/ldap/10_owncloud_schema.ldif @@ -0,0 +1,9 @@ +# This LDIF files describes the ownCloud schema and can be used to +# add two optional attributes: ownCloudQuota and ownCloudUUID +# The ownCloudUUID is used to store a unique, non-reassignable, persistent identifier for users and groups +dn: cn=owncloud,cn=schema,cn=config +objectClass: olcSchemaConfig +cn: owncloud +olcAttributeTypes: ( 1.3.6.1.4.1.39430.1.1.1 NAME 'ownCloudQuota' DESC 'User Quota (e.g. 2 GB)' EQUALITY caseExactMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.15 SINGLE-VALUE ) +olcAttributeTypes: ( 1.3.6.1.4.1.39430.1.1.2 NAME 'ownCloudUUID' DESC 'A non-reassignable and persistent account ID)' EQUALITY uuidMatch SUBSTR caseIgnoreSubstringsMatch SYNTAX 1.3.6.1.1.16.1 SINGLE-VALUE ) +olcObjectClasses: ( 1.3.6.1.4.1.39430.1.2.1 NAME 'ownCloud' DESC 'ownCloud LDAP Schema' AUXILIARY MAY ( ownCloudQuota $ ownCloudUUID ) ) diff --git a/tests/integration/grpc/fixtures/ldap/20_users.ldif b/tests/integration/grpc/fixtures/ldap/20_users.ldif new file mode 100644 index 0000000000..243008273c --- /dev/null +++ b/tests/integration/grpc/fixtures/ldap/20_users.ldif @@ -0,0 +1,84 @@ +dn: ou=users,dc=owncloud,dc=com +objectClass: organizationalUnit +ou: users + +# Start dn with uid (user identifier / login), not cn (Firstname + Surname) +dn: uid=einstein,ou=users,dc=owncloud,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: ownCloud +objectClass: person +objectClass: posixAccount +objectClass: top +uid: einstein +givenName: Albert +sn: Einstein +cn: einstein +displayName: Albert Einstein +description: A German-born theoretical physicist who developed the theory of relativity, one of the two pillars of modern physics (alongside quantum mechanics). +mail: einstein@example.org +uidNumber: 123 +gidNumber: 30000 +homeDirectory: /home/einstein +ownCloudUUID:: NGM1MTBhZGEtYzg2Yi00ODE1LTg4MjAtNDJjZGY4MmMzZDUx +userPassword:: e1NTSEF9TXJEcXpFNGdKbXZxbVRVTGhvWEZ1VzJBbkV3NWFLK3J3WTIvbHc9PQ== + +dn: uid=marie,ou=users,dc=owncloud,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: ownCloud +objectClass: person +objectClass: posixAccount +objectClass: top +uid: marie +givenName: Marie +sn: Curie +cn: marie +displayName: Marie Curie +description: A Polish and naturalized-French physicist and chemist who conducted pioneering research on radioactivity. +mail: marie@example.org +uidNumber: 20001 +gidNumber: 30000 +homeDirectory: /home/marie +ownCloudUUID:: ZjdmYmY4YzgtMTM5Yi00Mzc2LWIzMDctY2YwYThjMmQwZDlj +userPassword:: e1NTSEF9UmFvQWs3TU9jRHBIUWY3bXN3MGhHNnVraFZQWnRIRlhOSUNNZEE9PQ== + +dn: uid=richard,ou=users,dc=owncloud,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: ownCloud +objectClass: person +objectClass: posixAccount +objectClass: top +uid: richard +givenName: Richard +sn: Feynman +cn: richard +displayName: Richard Phillips Feynman +description: An American theoretical physicist, known for his work in the path integral formulation of quantum mechanics, the theory of quantum electrodynamics, the physics of the superfluidity of supercooled liquid helium, as well as his work in particle physics for which he proposed the parton model. +mail: richard@example.org +uidNumber: 20002 +gidNumber: 30000 +homeDirectory: /home/richard +ownCloudUUID:: OTMyYjQ1NDAtOGQxNi00ODFlLThlZjQtNTg4ZTRiNmIxNTFj +userPassword:: e1NTSEF9Z05LZTRreHdmOGRUREY5eHlhSmpySTZ3MGxSVUM1d1RGcWROTVE9PQ== + +dn: uid=moss,ou=users,dc=owncloud,dc=com +objectClass: inetOrgPerson +objectClass: organizationalPerson +objectClass: ownCloud +objectClass: person +objectClass: posixAccount +objectClass: top +uid: moss +givenName: Maurice +sn: Moss +cn: moss +displayName: Maurice Moss +description: A worker in the IT Department of Reynholm Industries. Of all the working staff in the IT Department, he is the most hard-working, the most experienced, and the most capable of doing his job well. He puts a lot of effort into his work, however he does not get the credit he deserves. +mail: moss@example.org +uidNumber: 20003 +gidNumber: 30000 +homeDirectory: /home/moss +ownCloudUUID:: MDU4YmZmOTUtNjcwOC00ZmU1LTkxZTQtOWVhM2QzNzc1ODhi +userPassword:: e1NTSEF9N0hEdTRoMkFDVExFWWt4U0RtSDZVQjhmUlpKRExDZDc= diff --git a/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif b/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif new file mode 100644 index 0000000000..d3a9c81837 --- /dev/null +++ b/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif @@ -0,0 +1,75 @@ +dn: ou=groups,dc=owncloud,dc=com +objectClass: organizationalUnit +ou: groups + +dn: cn=sailing-lovers,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: sailing-lovers +description: Sailing lovers +gidNumber: 30001 +ownCloudUUID:: NjA0MGFhMTctOWM2NC00ZmVmLTliZDAtNzcyMzRkNzFiYWQw +memberUid: einstein + +dn: cn=violin-haters,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: violin-haters +description: Violin haters +gidNumber: 30002 +ownCloudUUID:: ZGQ1OGU1ZWMtODQyZS00OThiLTg4MDAtNjFmMmVjNmY5MTFm +memberUid: einstein + +dn: cn=radium-lovers,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: radium-lovers +description: Radium lovers +gidNumber: 30003 +ownCloudUUID:: N2I4N2ZkNDktMjg2ZS00YTVmLWJhZmQtYzUzNWQ1ZGQ5OTdh +memberUid: marie + +dn: cn=polonium-lovers,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: polonium-lovers +description: Polonium lovers +gidNumber: 30004 +ownCloudUUID:: Y2VkYzIxYWEtNDA3Mi00NjE0LTg2NzYtZmE5MTY1ZjU5OGZm +memberUid: marie + +dn: cn=quantum-lovers,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: quantum-lovers +description: Quantum lovers +gidNumber: 30005 +ownCloudUUID:: YTE3MjYxMDgtMDFmOC00YzMwLTg4ZGYtMmIxYTlkMWNiYTFh +memberUid: richard + +dn: cn=philosophy-haters,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: philosophy-haters +description: Philosophy haters +gidNumber: 30006 +ownCloudUUID:: MTY3Y2JlZTItMDUxOC00NTVhLWJmYjItMDMxZmUwNjIxZTVk +memberUid: richard + +dn: cn=physics-lovers,ou=groups,dc=owncloud,dc=com +objectClass: posixGroup +objectClass: ownCloud +objectClass: top +cn: physics-lovers +description: Physics lovers +gidNumber: 30007 +ownCloudUUID:: MjYyOTgyYzEtMjM2Mi00YWZhLWJmZGYtOGNiZmVmNjRhMDZl +memberUid: einstein +memberUid: marie +memberUid: richard diff --git a/tests/integration/grpc/fixtures/userprovider-ldap.toml b/tests/integration/grpc/fixtures/userprovider-ldap.toml new file mode 100644 index 0000000000..97ab6a5b52 --- /dev/null +++ b/tests/integration/grpc/fixtures/userprovider-ldap.toml @@ -0,0 +1,25 @@ +[grpc] +address = "{{grpc_address}}" + +[grpc.services.userprovider] +driver = "ldap" + +[grpc.services.userprovider.drivers.ldap] +hostname="localhost" +port=10389 +insecure=true +base_dn="dc=owncloud,dc=com" +userfilter="(&(objectclass=posixAccount)(ownclouduuid={{.OpaqueId}}))" +findfilter="(&(objectclass=posixAccount)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)(ownclouduuid={{query}})))" +attributefilter="(&(objectclass=posixAccount)({{attr}}={{value}}))" +groupfilter="(&(objectclass=posixGroup)(cn=*)(memberuid={{query}}))" +bind_username="cn=admin,dc=owncloud,dc=com" +bind_password="admin" +idp="http://localhost:20080" + +[grpc.services.userprovider.drivers.ldap.schema] +uid="ownclouduuid" +displayName="displayName" +dn="dn" +cn="cn" +gid="cn" diff --git a/tests/integration/grpc/userprovider_test.go b/tests/integration/grpc/userprovider_test.go index 95a7e520f2..b8cde8651f 100644 --- a/tests/integration/grpc/userprovider_test.go +++ b/tests/integration/grpc/userprovider_test.go @@ -20,6 +20,7 @@ package grpc_test import ( "context" + "os" userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" @@ -266,4 +267,21 @@ var _ = Describe("user providers", func() { assertFindUsersResponses() assertGetUserByClaimResponses() }) + + Describe("the ldap userprovider", func() { + runldap := os.Getenv("RUN_LDAP_TESTS") + BeforeEach(func() { + if runldap == "" { + Skip("Skipping LDAP tests") + } + dependencies = map[string]string{ + "users": "userprovider-ldap.toml", + } + existingIdp = "http://localhost:20080" + }) + + assertGetUserResponses() + assertFindUsersResponses() + assertGetUserByClaimResponses() + }) }) From 6db51819a7c60601ac74656c44950f48f0e05069 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 23 Feb 2022 14:44:47 +0100 Subject: [PATCH 2/3] LDAP GetUser/GetGroup take IDP attribute into account If GetUser/GetGroup is called with the IDP attribute set to a non-empty string we only return results if the IDP setting configured for the user/groupprovider matches the IDP from the request. This aligns the LDAP providers' behaviour with what the demo and json providers implement. --- pkg/group/manager/ldap/ldap.go | 3 +++ pkg/user/manager/ldap/ldap.go | 5 +++++ 2 files changed, 8 insertions(+) diff --git a/pkg/group/manager/ldap/ldap.go b/pkg/group/manager/ldap/ldap.go index d2b9f1eea3..3d05f40abc 100644 --- a/pkg/group/manager/ldap/ldap.go +++ b/pkg/group/manager/ldap/ldap.go @@ -131,6 +131,9 @@ func New(m map[string]interface{}) (group.Manager, error) { func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId) (*grouppb.Group, error) { log := appctx.GetLogger(ctx) + if gid.Idp != "" && gid.Idp != m.c.Idp { + return nil, errtypes.NotFound("idp mismatch") + } l, err := utils.GetLDAPConnection(&m.c.LDAPConn) if err != nil { return nil, err diff --git a/pkg/user/manager/ldap/ldap.go b/pkg/user/manager/ldap/ldap.go index 282b35e638..6f8417b5fa 100644 --- a/pkg/user/manager/ldap/ldap.go +++ b/pkg/user/manager/ldap/ldap.go @@ -139,6 +139,11 @@ func (m *manager) Configure(ml map[string]interface{}) error { func (m *manager) GetUser(ctx context.Context, uid *userpb.UserId) (*userpb.User, error) { log := appctx.GetLogger(ctx) + + if uid.Idp != "" && uid.Idp != m.c.Idp { + return nil, errtypes.NotFound("idp mismatch") + } + l, err := utils.GetLDAPConnection(&m.c.LDAPConn) if err != nil { return nil, err From 169bcdbc847423b279b9dcefb738d4c8468802c1 Mon Sep 17 00:00:00 2001 From: Ralf Haferkamp Date: Wed, 23 Feb 2022 14:52:00 +0000 Subject: [PATCH 3/3] Address ginkgo v2 deprecation warnings CurrentGinkgoTestDescription() is deprecated in V2 and should be replaced with CurrentSpecReport(). --- tests/integration/grpc/gateway_storageprovider_test.go | 2 +- tests/integration/grpc/storageprovider_test.go | 2 +- tests/integration/grpc/userprovider_test.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/integration/grpc/gateway_storageprovider_test.go b/tests/integration/grpc/gateway_storageprovider_test.go index 07bd12ecc3..2a3abbb5a6 100644 --- a/tests/integration/grpc/gateway_storageprovider_test.go +++ b/tests/integration/grpc/gateway_storageprovider_test.go @@ -123,7 +123,7 @@ var _ = Describe("gateway", func() { AfterEach(func() { for _, r := range revads { - Expect(r.Cleanup(CurrentGinkgoTestDescription().Failed)).To(Succeed()) + Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) } }) diff --git a/tests/integration/grpc/storageprovider_test.go b/tests/integration/grpc/storageprovider_test.go index c7399b32c7..2679c98b19 100644 --- a/tests/integration/grpc/storageprovider_test.go +++ b/tests/integration/grpc/storageprovider_test.go @@ -123,7 +123,7 @@ var _ = Describe("storage providers", func() { AfterEach(func() { for _, r := range revads { - Expect(r.Cleanup(CurrentGinkgoTestDescription().Failed)).To(Succeed()) + Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) } }) diff --git a/tests/integration/grpc/userprovider_test.go b/tests/integration/grpc/userprovider_test.go index b8cde8651f..fd78c514e1 100644 --- a/tests/integration/grpc/userprovider_test.go +++ b/tests/integration/grpc/userprovider_test.go @@ -75,7 +75,7 @@ var _ = Describe("user providers", func() { AfterEach(func() { for _, r := range revads { - Expect(r.Cleanup(CurrentGinkgoTestDescription().Failed)) + Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) } })