From: Lucas Di Pentima Date: Fri, 8 Jan 2021 15:24:14 +0000 (-0300) Subject: 16981: Adds federation test on sync-groups. X-Git-Tag: 2.2.0~163^2~2 X-Git-Url: https://git.arvados.org/arvados.git/commitdiff_plain/59e8b47bee1c9699cbb2d16369481bd688da6e3d 16981: Adds federation test on sync-groups. Makes sure that running the tool on a federated cluster with admin credentials from the LoginCluster works correctly. Arvados-DCO-1.1-Signed-off-by: Lucas Di Pentima --- diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go index 33c68ce6e3..7e719e72ed 100644 --- a/lib/controller/integration_test.go +++ b/lib/controller/integration_test.go @@ -74,8 +74,6 @@ func (s *IntegrationSuite) SetUpSuite(c *check.C) { ExternalURL: https://` + hostport[id] + ` TLS: Insecure: true - Login: - LoginCluster: z1111 SystemLogs: Format: text RemoteClusters: diff --git a/sdk/go/arvadostest/federation_servers.go b/sdk/go/arvadostest/test_cluster.go similarity index 100% rename from sdk/go/arvadostest/federation_servers.go rename to sdk/go/arvadostest/test_cluster.go diff --git a/tools/sync-groups/federation_test.go b/tools/sync-groups/federation_test.go new file mode 100644 index 0000000000..2462383f3e --- /dev/null +++ b/tools/sync-groups/federation_test.go @@ -0,0 +1,202 @@ +// Copyright (C) The Arvados Authors. All rights reserved. +// +// SPDX-License-Identifier: AGPL-3.0 + +package main + +import ( + "net" + "os" + "path/filepath" + + "git.arvados.org/arvados.git/sdk/go/arvados" + "git.arvados.org/arvados.git/sdk/go/arvadostest" + check "gopkg.in/check.v1" +) + +var _ = check.Suite(&FederationSuite{}) + +var origAPIHost, origAPIToken string + +type FederationSuite struct { + testClusters map[string]*arvadostest.TestCluster + oidcprovider *arvadostest.OIDCProvider +} + +func (s *FederationSuite) SetUpSuite(c *check.C) { + origAPIHost = os.Getenv("ARVADOS_API_HOST") + origAPIToken = os.Getenv("ARVADOS_API_TOKEN") + + cwd, _ := os.Getwd() + + s.oidcprovider = arvadostest.NewOIDCProvider(c) + s.oidcprovider.AuthEmail = "user@example.com" + s.oidcprovider.AuthEmailVerified = true + s.oidcprovider.AuthName = "Example User" + s.oidcprovider.ValidClientID = "clientid" + s.oidcprovider.ValidClientSecret = "clientsecret" + + s.testClusters = map[string]*arvadostest.TestCluster{ + "z1111": nil, + "z2222": nil, + } + hostport := map[string]string{} + for id := range s.testClusters { + hostport[id] = func() string { + // TODO: Instead of expecting random ports on + // 127.0.0.11, 22 to be race-safe, try + // different 127.x.y.z until finding one that + // isn't in use. + ln, err := net.Listen("tcp", ":0") + c.Assert(err, check.IsNil) + ln.Close() + _, port, err := net.SplitHostPort(ln.Addr().String()) + c.Assert(err, check.IsNil) + return "127.0.0." + id[3:] + ":" + port + }() + } + for id := range s.testClusters { + yaml := `Clusters: + ` + id + `: + Services: + Controller: + ExternalURL: https://` + hostport[id] + ` + TLS: + Insecure: true + SystemLogs: + Format: text + RemoteClusters: + z1111: + Host: ` + hostport["z1111"] + ` + Scheme: https + Insecure: true + Proxy: true + ActivateUsers: true +` + if id != "z2222" { + yaml += ` z2222: + Host: ` + hostport["z2222"] + ` + Scheme: https + Insecure: true + Proxy: true + ActivateUsers: true +` + } + if id == "z1111" { + yaml += ` + Login: + LoginCluster: z1111 + OpenIDConnect: + Enable: true + Issuer: ` + s.oidcprovider.Issuer.URL + ` + ClientID: ` + s.oidcprovider.ValidClientID + ` + ClientSecret: ` + s.oidcprovider.ValidClientSecret + ` + EmailClaim: email + EmailVerifiedClaim: email_verified +` + } else { + yaml += ` + Login: + LoginCluster: z1111 +` + } + + tc, err := arvadostest.NewTestCluster( + filepath.Join(cwd, "..", ".."), + id, yaml, "127.0.0."+id[3:], c.Log) + c.Assert(err, check.IsNil) + s.testClusters[id] = tc + s.testClusters[id].Start() + } + for _, tc := range s.testClusters { + ok := tc.WaitReady() + c.Assert(ok, check.Equals, true) + } + + // Activate user, make it admin. + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + userctx1, _, _, _ := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, s.oidcprovider.AuthEmail, true) + user1, err := conn1.UserGetCurrent(userctx1, arvados.GetOptions{}) + c.Assert(err, check.IsNil) + c.Assert(user1.IsAdmin, check.Equals, false) + user1, err = conn1.UserUpdate(rootctx1, arvados.UpdateOptions{ + UUID: user1.UUID, + Attrs: map[string]interface{}{ + "is_admin": true, + }, + }) + c.Assert(err, check.IsNil) + c.Assert(user1.IsAdmin, check.Equals, true) +} + +func (s *FederationSuite) TearDownSuite(c *check.C) { + for _, c := range s.testClusters { + c.Super.Stop() + } + _ = os.Setenv("ARVADOS_API_HOST", origAPIHost) + _ = os.Setenv("ARVADOS_API_TOKEN", origAPIToken) +} + +func (s *FederationSuite) TestGroupSyncingOnFederatedCluster(c *check.C) { + // Get admin user's V2 token + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + userctx1, _, _, _ := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, s.oidcprovider.AuthEmail, true) + user1Auth, err := conn1.APIClientAuthorizationCurrent(userctx1, arvados.GetOptions{}) + c.Check(err, check.IsNil) + userV2Token := user1Auth.TokenV2() + + // Get federated admin clients on z2222 to set up environment + conn2 := s.testClusters["z2222"].Conn() + userctx2, userac2, _ := s.testClusters["z2222"].ClientsWithToken(userV2Token) + user2, err := conn2.UserGetCurrent(userctx2, arvados.GetOptions{}) + c.Check(err, check.IsNil) + c.Check(user2.IsAdmin, check.Equals, true) + + // Set up environment for sync-groups using admin user credentials on z2222 + err = os.Setenv("ARVADOS_API_HOST", userac2.APIHost) + c.Assert(err, check.IsNil) + err = os.Setenv("ARVADOS_API_TOKEN", userac2.AuthToken) + c.Assert(err, check.IsNil) + + // Check that no parent group is created + gl := arvados.GroupList{} + params := arvados.ResourceListParams{ + Filters: []arvados.Filter{{ + Attr: "owner_uuid", + Operator: "=", + Operand: s.testClusters["z2222"].ClusterID + "-tpzed-000000000000000", + }, { + Attr: "name", + Operator: "=", + Operand: "Externally synchronized groups", + }}, + } + err = userac2.RequestAndDecode(&gl, "GET", "/arvados/v1/groups", nil, params) + c.Assert(err, check.IsNil) + c.Assert(gl.ItemsAvailable, check.Equals, 0) + + // Set up config, confirm that the parent group was created + os.Args = []string{"cmd", "somefile.csv"} + config, err := GetConfig() + c.Assert(err, check.IsNil) + userac2.RequestAndDecode(&gl, "GET", "/arvados/v1/groups", nil, params) + c.Assert(gl.ItemsAvailable, check.Equals, 1) + + // Run the tool with custom config + data := [][]string{ + {"TestGroup1", user2.Email}, + } + tmpfile, err := MakeTempCSVFile(data) + c.Assert(err, check.IsNil) + defer os.Remove(tmpfile.Name()) // clean up + config.Path = tmpfile.Name() + err = doMain(&config) + c.Assert(err, check.IsNil) + // Check the group was created correctly, and has the user as a member + groupUUID, err := RemoteGroupExists(&config, "TestGroup1") + c.Assert(err, check.IsNil) + c.Assert(groupUUID, check.Not(check.Equals), "") + c.Assert(GroupMembershipExists(config.Client, user2.UUID, groupUUID, "can_write"), check.Equals, true) +}