diff --git a/changelog/unreleased/group-integration-tests.md b/changelog/unreleased/group-integration-tests.md new file mode 100644 index 0000000000..5fe152d828 --- /dev/null +++ b/changelog/unreleased/group-integration-tests.md @@ -0,0 +1,5 @@ +Enhancement: Add integration test for the groupprovider + +Some new integration tests were added to cover the groupprovider. + +https://github.com/cs3org/reva/pull/2595 diff --git a/pkg/group/manager/json/json.go b/pkg/group/manager/json/json.go index ad4a425dd6..a5a976a287 100644 --- a/pkg/group/manager/json/json.go +++ b/pkg/group/manager/json/json.go @@ -89,7 +89,7 @@ func New(m map[string]interface{}) (group.Manager, error) { func (m *manager) GetGroup(ctx context.Context, gid *grouppb.GroupId) (*grouppb.Group, error) { for _, g := range m.groups { - if g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId { + if (g.Id.GetOpaqueId() == gid.OpaqueId || g.GroupName == gid.OpaqueId) && (gid.Idp == "" || gid.Idp == g.Id.GetIdp()) { return g, nil } } diff --git a/tests/integration/grpc/fixtures/groupprovider-json.toml b/tests/integration/grpc/fixtures/groupprovider-json.toml new file mode 100644 index 0000000000..d4a5300067 --- /dev/null +++ b/tests/integration/grpc/fixtures/groupprovider-json.toml @@ -0,0 +1,11 @@ +[log] +level = "debug" + +[grpc] +address = "{{grpc_address}}" + +[grpc.services.groupprovider] +driver = "json" + +[grpc.services.groupprovider.drivers.json] +groups = "fixtures/groups.demo.json" diff --git a/tests/integration/grpc/fixtures/groupprovider-ldap.toml b/tests/integration/grpc/fixtures/groupprovider-ldap.toml new file mode 100644 index 0000000000..c22485686a --- /dev/null +++ b/tests/integration/grpc/fixtures/groupprovider-ldap.toml @@ -0,0 +1,27 @@ +[log] +level = "debug" + +[grpc] +address = "{{grpc_address}}" + +[grpc.services.groupprovider] +driver = "ldap" + +[grpc.services.groupprovider.drivers.ldap] +hostname="ocisldap" +port=636 +insecure=true +base_dn="dc=owncloud,dc=com" +groupfilter="(&(objectclass=posixGroup)(ownclouduuid={{.OpaqueId}}))" +memberfilter="(&(objectclass=posixGroup)(ownclouduuid={{.OpaqueId}}))" +findfilter="(&(objectclass=posixGroup)(|(cn={{query}}*)(displayname={{query}}*)(mail={{query}}*)(ownclouduuid={{query}})))" +attributefilter="(&(objectclass=posixGroup)({{attr}}={{value}}))" +bind_username="cn=admin,dc=owncloud,dc=com" +bind_password="admin" +idp="http://localhost:20080" + +[grpc.services.groupprovider.drivers.ldap.schema] +gid="ownclouduuid" +displayName="description" +dn="dn" +cn="cn" diff --git a/tests/integration/grpc/fixtures/groups.demo.json b/tests/integration/grpc/fixtures/groups.demo.json new file mode 100644 index 0000000000..3ebdb701a3 --- /dev/null +++ b/tests/integration/grpc/fixtures/groups.demo.json @@ -0,0 +1,113 @@ +[ + { + "id": { + "opaque_id": "6040aa17-9c64-4fef-9bd0-77234d71bad0", + "idp": "http://localhost:20080" + }, + "group_name": "sailing-lovers", + "gidNumber" : "30001", + "display_name": "Sailing Lovers", + "members": [ + { + "opaque_id": "4c510ada-c86b-4815-8820-42cdf82c3d51", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "dd58e5ec-842e-498b-8800-61f2ec6f911f", + "idp": "http://localhost:20080" + }, + "group_name": "violin-haters", + "gidNumber" : "30002", + "display_name": "Violin Haters", + "members": [ + { + "opaque_id": "4c510ada-c86b-4815-8820-42cdf82c3d51", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "7b87fd49-286e-4a5f-bafd-c535d5dd997a", + "idp": "http://localhost:20080" + }, + "group_name": "radium-lovers", + "gidNumber" : "30003", + "display_name": "Radium Lovers", + "members": [ + { + "opaque_id": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "cedc21aa-4072-4614-8676-fa9165f598ff", + "idp": "http://localhost:20080" + }, + "group_name": "polonium-lovers", + "gidNumber" : "30004", + "display_name": "Polonium Lovers", + "members": [ + { + "opaque_id": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "a1726108-01f8-4c30-88df-2b1a9d1cba1a", + "idp": "http://localhost:20080" + }, + "group_name": "quantum-lovers", + "gidNumber" : "30005", + "display_name": "Quantum Lovers", + "members": [ + { + "opaque_id": "932b4540-8d16-481e-8ef4-588e4b6b151c", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "167cbee2-0518-455a-bfb2-031fe0621e5d", + "idp": "http://localhost:20080" + }, + "group_name": "philosophy-haters", + "gidNumber" : "30006", + "display_name": "Philosophy Haters", + "members": [ + { + "opaque_id": "932b4540-8d16-481e-8ef4-588e4b6b151c", + "idp": "http://localhost:20080" + } + ] + }, + { + "id": { + "opaque_id": "262982c1-2362-4afa-bfdf-8cbfef64a06e", + "idp": "http://localhost:20080" + }, + "group_name": "physics-lovers", + "gidNumber" : "30005", + "display_name": "Physics Lovers", + "members": [ + { + "opaque_id": "4c510ada-c86b-4815-8820-42cdf82c3d51", + "idp": "http://localhost:20080" + },{ + "opaque_id": "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + "idp": "http://localhost:20080" + },{ + "opaque_id": "932b4540-8d16-481e-8ef4-588e4b6b151c", + "idp": "http://localhost:20080" + } + ] + } +] diff --git a/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif b/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif index d3a9c81837..4976cb483a 100644 --- a/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif +++ b/tests/integration/grpc/fixtures/ldap/30_groups_rfc2307.ldif @@ -2,12 +2,12 @@ dn: ou=groups,dc=owncloud,dc=com objectClass: organizationalUnit ou: groups -dn: cn=sailing-lovers,ou=groups,dc=owncloud,dc=com +dn: cn=Sailing Lovers,ou=groups,dc=owncloud,dc=com objectClass: posixGroup objectClass: ownCloud objectClass: top cn: sailing-lovers -description: Sailing lovers +description: Sailing Lovers gidNumber: 30001 ownCloudUUID:: NjA0MGFhMTctOWM2NC00ZmVmLTliZDAtNzcyMzRkNzFiYWQw memberUid: einstein @@ -17,7 +17,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: violin-haters -description: Violin haters +description: Violin Haters gidNumber: 30002 ownCloudUUID:: ZGQ1OGU1ZWMtODQyZS00OThiLTg4MDAtNjFmMmVjNmY5MTFm memberUid: einstein @@ -27,7 +27,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: radium-lovers -description: Radium lovers +description: Radium Lovers gidNumber: 30003 ownCloudUUID:: N2I4N2ZkNDktMjg2ZS00YTVmLWJhZmQtYzUzNWQ1ZGQ5OTdh memberUid: marie @@ -37,7 +37,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: polonium-lovers -description: Polonium lovers +description: Polonium Lovers gidNumber: 30004 ownCloudUUID:: Y2VkYzIxYWEtNDA3Mi00NjE0LTg2NzYtZmE5MTY1ZjU5OGZm memberUid: marie @@ -47,7 +47,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: quantum-lovers -description: Quantum lovers +description: Quantum Lovers gidNumber: 30005 ownCloudUUID:: YTE3MjYxMDgtMDFmOC00YzMwLTg4ZGYtMmIxYTlkMWNiYTFh memberUid: richard @@ -57,7 +57,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: philosophy-haters -description: Philosophy haters +description: Philosophy Haters gidNumber: 30006 ownCloudUUID:: MTY3Y2JlZTItMDUxOC00NTVhLWJmYjItMDMxZmUwNjIxZTVk memberUid: richard @@ -67,7 +67,7 @@ objectClass: posixGroup objectClass: ownCloud objectClass: top cn: physics-lovers -description: Physics lovers +description: Physics Lovers gidNumber: 30007 ownCloudUUID:: MjYyOTgyYzEtMjM2Mi00YWZhLWJmZGYtOGNiZmVmNjRhMDZl memberUid: einstein diff --git a/tests/integration/grpc/groupprovider_test.go b/tests/integration/grpc/groupprovider_test.go new file mode 100644 index 0000000000..5849e77733 --- /dev/null +++ b/tests/integration/grpc/groupprovider_test.go @@ -0,0 +1,273 @@ +// Copyright 2018-2021 CERN +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. +// +// In applying this license, CERN does not waive the privileges and immunities +// granted to it by virtue of its status as an Intergovernmental Organization +// or submit itself to any jurisdiction. + +package grpc_test + +import ( + "context" + "os" + + grouppb "github.com/cs3org/go-cs3apis/cs3/identity/group/v1beta1" + userpb "github.com/cs3org/go-cs3apis/cs3/identity/user/v1beta1" + rpc "github.com/cs3org/go-cs3apis/cs3/rpc/v1beta1" + "github.com/cs3org/reva/pkg/auth/scope" + ctxpkg "github.com/cs3org/reva/pkg/ctx" + "github.com/cs3org/reva/pkg/rgrpc/todo/pool" + jwt "github.com/cs3org/reva/pkg/token/manager/jwt" + "google.golang.org/grpc/metadata" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" +) + +var _ = Describe("group providers", func() { + var ( + dependencies map[string]string + revads map[string]*Revad + + existingIdp string + + ctx context.Context + serviceClient grouppb.GroupAPIClient + ) + + JustBeforeEach(func() { + var err error + ctx = context.Background() + + // Add auth token + user := &userpb.User{ + Id: &userpb.UserId{ + Idp: existingIdp, + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Type: userpb.UserType_USER_TYPE_PRIMARY, + }, + } + tokenManager, err := jwt.New(map[string]interface{}{"secret": "changemeplease"}) + Expect(err).ToNot(HaveOccurred()) + scope, err := scope.AddOwnerScope(nil) + Expect(err).ToNot(HaveOccurred()) + t, err := tokenManager.MintToken(ctx, user, scope) + Expect(err).ToNot(HaveOccurred()) + ctx = ctxpkg.ContextSetToken(ctx, t) + ctx = metadata.AppendToOutgoingContext(ctx, ctxpkg.TokenHeader, t) + ctx = ctxpkg.ContextSetUser(ctx, user) + + revads, err = startRevads(dependencies, map[string]string{}) + Expect(err).ToNot(HaveOccurred()) + serviceClient, err = pool.GetGroupProviderServiceClient(revads["groups"].GrpcAddress) + Expect(err).ToNot(HaveOccurred()) + }) + + AfterEach(func() { + for _, r := range revads { + Expect(r.Cleanup(CurrentSpecReport().Failed())).To(Succeed()) + } + }) + + var assertGetGroupByClaimResponses = func() { + It("gets groups by claim as expected", func() { + tests := map[string]string{ + "group_name": "violin-haters", + "display_name": "Violin Haters", + } + + for claim, value := range tests { + group, err := serviceClient.GetGroupByClaim(ctx, &grouppb.GetGroupByClaimRequest{Claim: claim, Value: value}) + Expect(err).ToNot(HaveOccurred()) + Expect(group.Group).ToNot(BeNil()) + Expect(group.Group.DisplayName).To(Equal("Violin Haters")) + Expect(group.Group.Id.OpaqueId).To(Equal("dd58e5ec-842e-498b-8800-61f2ec6f911f")) + } + }) + } + + var assertGetGroupResponses = func() { + It("gets groups as expected", func() { + tests := []struct { + name string + groupID *grouppb.GroupId + want *grouppb.GetGroupResponse + }{ + { + name: "simple", + groupID: &grouppb.GroupId{ + Idp: existingIdp, + OpaqueId: "6040aa17-9c64-4fef-9bd0-77234d71bad0", + }, + want: &grouppb.GetGroupResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_OK, + }, + Group: &grouppb.Group{ + GroupName: "sailing-lovers", + Mail: "marie@example.org", + DisplayName: "Sailing Lovers", + Members: []*userpb.UserId{ + { + OpaqueId: "4c510ada-c86b-4815-8820-42cdf82c3d51", + Idp: "http://localhost:20080", + }, + }, + }, + }, + }, + { + name: "not-existing opaqueId", + groupID: &grouppb.GroupId{ + Idp: existingIdp, + OpaqueId: "doesnote-xist-4376-b307-cf0a8c2d0d9c", + }, + want: &grouppb.GetGroupResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_NOT_FOUND, + }, + }, + }, + { + name: "no opaqueId", + groupID: &grouppb.GroupId{ + Idp: existingIdp, + }, + want: &grouppb.GetGroupResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_NOT_FOUND, + }, + }, + }, + { + name: "not-existing idp", + groupID: &grouppb.GroupId{ + Idp: "http://does-not-exist:12345", + OpaqueId: "262982c1-2362-4afa-bfdf-8cbfef64a06e", + }, + want: &grouppb.GetGroupResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_NOT_FOUND, + }, + }, + }, + { + name: "no idp", + groupID: &grouppb.GroupId{ + OpaqueId: "262982c1-2362-4afa-bfdf-8cbfef64a06e", + }, + want: &grouppb.GetGroupResponse{ + Status: &rpc.Status{ + Code: rpc.Code_CODE_OK, + }, + Group: &grouppb.Group{ + GroupName: "physics-lovers", + DisplayName: "Physics Lovers", + Members: []*userpb.UserId{ + { + OpaqueId: "4c510ada-c86b-4815-8820-42cdf82c3d51", + Idp: "http://localhost:20080", + }, { + OpaqueId: "f7fbf8c8-139b-4376-b307-cf0a8c2d0d9c", + Idp: "http://localhost:20080", + }, { + OpaqueId: "932b4540-8d16-481e-8ef4-588e4b6b151c", + Idp: "http://localhost:20080", + }, + }, + }, + }, + }, + } + + for _, t := range tests { + groupResp, err := serviceClient.GetGroup(ctx, &grouppb.GetGroupRequest{ + GroupId: t.groupID, + }) + Expect(err).ToNot(HaveOccurred()) + Expect(t.want.Status.Code).To(Equal(groupResp.Status.Code)) + if t.want.Group == nil { + Expect(groupResp.Group).To(BeNil()) + } else { + // make sure not to run into a nil pointer error + Expect(groupResp.Group).ToNot(BeNil()) + Expect(t.want.Group.GroupName).To(Equal(groupResp.Group.GroupName)) + Expect(t.want.Group.DisplayName).To(Equal(groupResp.Group.DisplayName)) + if len(t.want.Group.Members) == 1 { + Expect(t.want.Group.Members[0].Idp).To(Equal(groupResp.Group.Members[0].Idp)) + Expect(t.want.Group.Members[0].OpaqueId).To(Equal(groupResp.Group.Members[0].OpaqueId)) + } else { + Expect(len(t.want.Group.Members)).To(Equal(len(groupResp.Group.Members))) + } + } + } + }) + } + + var assertFindGroupsResponses = func() { + It("finds groups by displayname", func() { + res, err := serviceClient.FindGroups(ctx, &grouppb.FindGroupsRequest{Filter: "Physics Lovers"}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(res.Groups)).To(Equal(1)) + group := res.Groups[0] + Expect(group.Id.OpaqueId).To(Equal("262982c1-2362-4afa-bfdf-8cbfef64a06e")) + }) + + It("finds groups by name", func() { + res, err := serviceClient.FindGroups(ctx, &grouppb.FindGroupsRequest{Filter: "physics-lovers"}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(res.Groups)).To(Equal(1)) + group := res.Groups[0] + Expect(group.Id.OpaqueId).To(Equal("262982c1-2362-4afa-bfdf-8cbfef64a06e")) + }) + + It("finds groups by id", func() { + res, err := serviceClient.FindGroups(ctx, &grouppb.FindGroupsRequest{Filter: "262982c1-2362-4afa-bfdf-8cbfef64a06e"}) + Expect(err).ToNot(HaveOccurred()) + Expect(len(res.Groups)).To(Equal(1)) + group := res.Groups[0] + Expect(group.Id.OpaqueId).To(Equal("262982c1-2362-4afa-bfdf-8cbfef64a06e")) + }) + } + + Describe("the json groupprovider", func() { + BeforeEach(func() { + dependencies = map[string]string{ + "groups": "groupprovider-json.toml", + } + existingIdp = "http://localhost:20080" + }) + + assertFindGroupsResponses() + assertGetGroupResponses() + assertGetGroupByClaimResponses() + }) + + Describe("the ldap groupprovider", func() { + runldap := os.Getenv("RUN_LDAP_TESTS") + BeforeEach(func() { + if runldap == "" { + Skip("Skipping LDAP tests") + } + dependencies = map[string]string{ + "groups": "groupprovider-ldap.toml", + } + existingIdp = "http://localhost:20080" + }) + + assertFindGroupsResponses() + assertGetGroupResponses() + assertGetGroupByClaimResponses() + }) +})