16981: Adds federation test on sync-groups.
authorLucas Di Pentima <lucas@di-pentima.com.ar>
Fri, 8 Jan 2021 15:24:14 +0000 (12:24 -0300)
committerLucas Di Pentima <lucas@di-pentima.com.ar>
Fri, 8 Jan 2021 15:24:14 +0000 (12:24 -0300)
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 <lucas@di-pentima.com.ar>

lib/controller/integration_test.go
sdk/go/arvadostest/test_cluster.go [moved from sdk/go/arvadostest/federation_servers.go with 100% similarity]
tools/sync-groups/federation_test.go [new file with mode: 0644]

index 33c68ce6e3a56e5c171aa3944bf2dff5aea110b3..7e719e72ed2918d5b1c5230bfa0ceeba33943c6b 100644 (file)
@@ -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/tools/sync-groups/federation_test.go b/tools/sync-groups/federation_test.go
new file mode 100644 (file)
index 0000000..2462383
--- /dev/null
@@ -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)
+}