X-Git-Url: https://git.arvados.org/arvados.git/blobdiff_plain/8889791d095df8578745e0a1b3c2f4a721f54123..0ce66018616c5177bc9268280119d6f08f339d4d:/lib/controller/integration_test.go diff --git a/lib/controller/integration_test.go b/lib/controller/integration_test.go index 0e95c19ea5..44c99bf30f 100644 --- a/lib/controller/integration_test.go +++ b/lib/controller/integration_test.go @@ -6,6 +6,8 @@ package controller import ( "bytes" + "context" + "database/sql" "encoding/json" "fmt" "io" @@ -35,11 +37,6 @@ type IntegrationSuite struct { } func (s *IntegrationSuite) SetUpSuite(c *check.C) { - if forceLegacyAPI14 { - c.Skip("heavy integration tests don't run with forceLegacyAPI14") - return - } - cwd, _ := os.Getwd() s.oidcprovider = arvadostest.NewOIDCProvider(c) @@ -116,6 +113,8 @@ func (s *IntegrationSuite) SetUpSuite(c *check.C) { ClientSecret: ` + s.oidcprovider.ValidClientSecret + ` EmailClaim: email EmailVerifiedClaim: email_verified + AcceptAccessToken: true + AcceptAccessTokenScope: "" ` } else { yaml += ` @@ -133,8 +132,9 @@ func (s *IntegrationSuite) SetUpSuite(c *check.C) { tc := boot.NewTestCluster( filepath.Join(cwd, "..", ".."), id, cfg, "127.0.0."+id[3:], c.Log) + tc.Super.NoWorkbench1 = true + tc.Start() s.testClusters[id] = tc - s.testClusters[id].Start() } for _, tc := range s.testClusters { ok := tc.WaitReady() @@ -362,6 +362,7 @@ func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) { c.Assert(err, check.IsNil) req.Header.Set("Content-Type", "application/json") err = ac2.DoAndDecode(&cr, req) + c.Assert(err, check.IsNil) c.Logf("err == %#v", err) c.Log("...get user with good token") @@ -388,10 +389,153 @@ func (s *IntegrationSuite) TestCreateContainerRequestWithFedToken(c *check.C) { req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "OAuth2 "+ac2.AuthToken) resp, err = arvados.InsecureHTTPClient.Do(req) - if c.Check(err, check.IsNil) { - err = json.NewDecoder(resp.Body).Decode(&cr) + c.Assert(err, check.IsNil) + err = json.NewDecoder(resp.Body).Decode(&cr) + c.Check(err, check.IsNil) + c.Check(cr.UUID, check.Matches, "z2222-.*") +} + +func (s *IntegrationSuite) TestCreateContainerRequestWithBadToken(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + _, ac1, _, au := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + tests := []struct { + name string + token string + expectedCode int + }{ + {"Good token", ac1.AuthToken, http.StatusOK}, + {"Bogus token", "abcdef", http.StatusUnauthorized}, + {"v1-looking token", "badtoken00badtoken00badtoken00badtoken00b", http.StatusUnauthorized}, + {"v2-looking token", "v2/" + au.UUID + "/badtoken00badtoken00badtoken00badtoken00b", http.StatusUnauthorized}, + } + + body, _ := json.Marshal(map[string]interface{}{ + "container_request": map[string]interface{}{ + "command": []string{"echo"}, + "container_image": "d41d8cd98f00b204e9800998ecf8427e+0", + "cwd": "/", + "output_path": "/", + }, + }) + + for _, tt := range tests { + c.Log(c.TestName() + " " + tt.name) + ac1.AuthToken = tt.token + req, err := http.NewRequest("POST", "https://"+ac1.APIHost+"/arvados/v1/container_requests", bytes.NewReader(body)) + c.Assert(err, check.IsNil) + req.Header.Set("Content-Type", "application/json") + resp, err := ac1.Do(req) + c.Assert(err, check.IsNil) + c.Assert(resp.StatusCode, check.Equals, tt.expectedCode) + } +} + +// We test the direct access to the database +// normally an integration test would not have a database access, but in this case we need +// to test tokens that are secret, so there is no API response that will give them back +func (s *IntegrationSuite) dbConn(c *check.C, clusterID string) (*sql.DB, *sql.Conn) { + ctx := context.Background() + db, err := sql.Open("postgres", s.testClusters[clusterID].Super.Cluster().PostgreSQL.Connection.String()) + c.Assert(err, check.IsNil) + + conn, err := db.Conn(ctx) + c.Assert(err, check.IsNil) + + rows, err := conn.ExecContext(ctx, `SELECT 1`) + c.Assert(err, check.IsNil) + n, err := rows.RowsAffected() + c.Assert(err, check.IsNil) + c.Assert(n, check.Equals, int64(1)) + return db, conn +} + +// TestRuntimeTokenInCR will test several different tokens in the runtime attribute +// and check the expected results accessing directly to the database if needed. +func (s *IntegrationSuite) TestRuntimeTokenInCR(c *check.C) { + db, dbconn := s.dbConn(c, "z1111") + defer db.Close() + defer dbconn.Close() + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + userctx1, ac1, _, au := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + tests := []struct { + name string + token string + expectAToGetAValidCR bool + expectedToken *string + }{ + {"Good token z1111 user", ac1.AuthToken, true, &ac1.AuthToken}, + {"Bogus token", "abcdef", false, nil}, + {"v1-looking token", "badtoken00badtoken00badtoken00badtoken00b", false, nil}, + {"v2-looking token", "v2/" + au.UUID + "/badtoken00badtoken00badtoken00badtoken00b", false, nil}, + } + + for _, tt := range tests { + c.Log(c.TestName() + " " + tt.name) + + rq := map[string]interface{}{ + "command": []string{"echo"}, + "container_image": "d41d8cd98f00b204e9800998ecf8427e+0", + "cwd": "/", + "output_path": "/", + "runtime_token": tt.token, + } + cr, err := conn1.ContainerRequestCreate(userctx1, arvados.CreateOptions{Attrs: rq}) + if tt.expectAToGetAValidCR { + c.Check(err, check.IsNil) + c.Check(cr, check.NotNil) + c.Check(cr.UUID, check.Not(check.Equals), "") + } + + if tt.expectedToken == nil { + continue + } + + c.Logf("cr.UUID: %s", cr.UUID) + row := dbconn.QueryRowContext(rootctx1, `SELECT runtime_token from container_requests where uuid=$1`, cr.UUID) + c.Check(row, check.NotNil) + var token sql.NullString + row.Scan(&token) + if c.Check(token.Valid, check.Equals, true) { + c.Check(token.String, check.Equals, *tt.expectedToken) + } + } +} + +// TestIntermediateCluster will send a container request to +// one cluster with another cluster as the destination +// and check the tokens are being handled properly +func (s *IntegrationSuite) TestIntermediateCluster(c *check.C) { + conn1 := s.testClusters["z1111"].Conn() + rootctx1, _, _ := s.testClusters["z1111"].RootClients() + uctx1, ac1, _, _ := s.testClusters["z1111"].UserClients(rootctx1, c, conn1, "user@example.com", true) + + tests := []struct { + name string + token string + expectedRuntimeToken string + expectedUUIDprefix string + }{ + {"Good token z1111 user sending a CR to z2222", ac1.AuthToken, "", "z2222-xvhdp-"}, + } + + for _, tt := range tests { + c.Log(c.TestName() + " " + tt.name) + rq := map[string]interface{}{ + "command": []string{"echo"}, + "container_image": "d41d8cd98f00b204e9800998ecf8427e+0", + "cwd": "/", + "output_path": "/", + "runtime_token": tt.token, + } + cr, err := conn1.ContainerRequestCreate(uctx1, arvados.CreateOptions{ClusterID: "z2222", Attrs: rq}) + c.Check(err, check.IsNil) - c.Check(cr.UUID, check.Matches, "z2222-.*") + c.Check(strings.HasPrefix(cr.UUID, tt.expectedUUIDprefix), check.Equals, true) + c.Check(cr.RuntimeToken, check.Equals, tt.expectedRuntimeToken) } } @@ -537,15 +681,16 @@ func (s *IntegrationSuite) TestOIDCAccessTokenAuth(c *check.C) { accesstoken := s.oidcprovider.ValidAccessToken() for _, clusterID := range []string{"z1111", "z2222"} { - c.Logf("trying clusterid %s", clusterID) - - conn := s.testClusters[clusterID].Conn() - ctx, ac, kc := s.testClusters[clusterID].ClientsWithToken(accesstoken) var coll arvados.Collection // Write some file data and create a collection { + c.Logf("save collection to %s", clusterID) + + conn := s.testClusters[clusterID].Conn() + ctx, ac, kc := s.testClusters[clusterID].ClientsWithToken(accesstoken) + fs, err := coll.FileSystem(ac, kc) c.Assert(err, check.IsNil) f, err := fs.OpenFile("test.txt", os.O_CREATE|os.O_RDWR, 0777) @@ -562,15 +707,22 @@ func (s *IntegrationSuite) TestOIDCAccessTokenAuth(c *check.C) { c.Assert(err, check.IsNil) } - // Read the collection & file data - { + // Read the collection & file data -- both from the + // cluster where it was created, and from the other + // cluster. + for _, readClusterID := range []string{"z1111", "z2222", "z3333"} { + c.Logf("retrieve %s from %s", coll.UUID, readClusterID) + + conn := s.testClusters[readClusterID].Conn() + ctx, ac, kc := s.testClusters[readClusterID].ClientsWithToken(accesstoken) + user, err := conn.UserGetCurrent(ctx, arvados.GetOptions{}) c.Assert(err, check.IsNil) c.Check(user.FullName, check.Equals, "Example User") - coll, err = conn.CollectionGet(ctx, arvados.GetOptions{UUID: coll.UUID}) + readcoll, err := conn.CollectionGet(ctx, arvados.GetOptions{UUID: coll.UUID}) c.Assert(err, check.IsNil) - c.Check(coll.ManifestText, check.Not(check.Equals), "") - fs, err := coll.FileSystem(ac, kc) + c.Check(readcoll.ManifestText, check.Not(check.Equals), "") + fs, err := readcoll.FileSystem(ac, kc) c.Assert(err, check.IsNil) f, err := fs.Open("test.txt") c.Assert(err, check.IsNil)