17755: Merge branch 'main' into 17755-add-singularity-to-compute-image
[arvados.git] / lib / controller / auth_test.go
1 // Copyright (C) The Arvados Authors. All rights reserved.
2 //
3 // SPDX-License-Identifier: AGPL-3.0
4
5 package controller
6
7 import (
8         "context"
9         "encoding/json"
10         "fmt"
11         "net/http"
12         "net/http/httptest"
13         "os"
14         "time"
15
16         "git.arvados.org/arvados.git/sdk/go/arvados"
17         "git.arvados.org/arvados.git/sdk/go/arvadostest"
18         "git.arvados.org/arvados.git/sdk/go/ctxlog"
19         "git.arvados.org/arvados.git/sdk/go/httpserver"
20         "github.com/sirupsen/logrus"
21         check "gopkg.in/check.v1"
22 )
23
24 // Gocheck boilerplate
25 var _ = check.Suite(&AuthSuite{})
26
27 type AuthSuite struct {
28         log logrus.FieldLogger
29         // testServer and testHandler are the controller being tested,
30         // "zhome".
31         testServer  *httpserver.Server
32         testHandler *Handler
33         // remoteServer ("zzzzz") forwards requests to the Rails API
34         // provided by the integration test environment.
35         remoteServer *httpserver.Server
36         // remoteMock ("zmock") appends each incoming request to
37         // remoteMockRequests, and returns 200 with an empty JSON
38         // object.
39         remoteMock         *httpserver.Server
40         remoteMockRequests []http.Request
41
42         fakeProvider *arvadostest.OIDCProvider
43 }
44
45 func (s *AuthSuite) SetUpTest(c *check.C) {
46         s.log = ctxlog.TestLogger(c)
47
48         s.remoteServer = newServerFromIntegrationTestEnv(c)
49         c.Assert(s.remoteServer.Start(), check.IsNil)
50
51         s.remoteMock = newServerFromIntegrationTestEnv(c)
52         s.remoteMock.Server.Handler = http.HandlerFunc(http.NotFound)
53         c.Assert(s.remoteMock.Start(), check.IsNil)
54
55         s.fakeProvider = arvadostest.NewOIDCProvider(c)
56         s.fakeProvider.AuthEmail = "active-user@arvados.local"
57         s.fakeProvider.AuthEmailVerified = true
58         s.fakeProvider.AuthName = "Fake User Name"
59         s.fakeProvider.ValidCode = fmt.Sprintf("abcdefgh-%d", time.Now().Unix())
60         s.fakeProvider.PeopleAPIResponse = map[string]interface{}{}
61         s.fakeProvider.ValidClientID = "test%client$id"
62         s.fakeProvider.ValidClientSecret = "test#client/secret"
63
64         cluster := &arvados.Cluster{
65                 ClusterID:       "zhome",
66                 PostgreSQL:      integrationTestCluster().PostgreSQL,
67                 SystemRootToken: arvadostest.SystemRootToken,
68         }
69         cluster.TLS.Insecure = true
70         cluster.API.MaxItemsPerResponse = 1000
71         cluster.API.MaxRequestAmplification = 4
72         cluster.API.RequestTimeout = arvados.Duration(5 * time.Minute)
73         arvadostest.SetServiceURL(&cluster.Services.RailsAPI, "https://"+os.Getenv("ARVADOS_TEST_API_HOST"))
74         arvadostest.SetServiceURL(&cluster.Services.Controller, "http://localhost/")
75
76         cluster.RemoteClusters = map[string]arvados.RemoteCluster{
77                 "zzzzz": {
78                         Host:   s.remoteServer.Addr,
79                         Proxy:  true,
80                         Scheme: "http",
81                 },
82                 "zmock": {
83                         Host:   s.remoteMock.Addr,
84                         Proxy:  true,
85                         Scheme: "http",
86                 },
87                 "*": {
88                         Scheme: "https",
89                 },
90         }
91         cluster.Login.OpenIDConnect.Enable = true
92         cluster.Login.OpenIDConnect.Issuer = s.fakeProvider.Issuer.URL
93         cluster.Login.OpenIDConnect.ClientID = s.fakeProvider.ValidClientID
94         cluster.Login.OpenIDConnect.ClientSecret = s.fakeProvider.ValidClientSecret
95         cluster.Login.OpenIDConnect.EmailClaim = "email"
96         cluster.Login.OpenIDConnect.EmailVerifiedClaim = "email_verified"
97         cluster.Login.OpenIDConnect.AcceptAccessToken = true
98         cluster.Login.OpenIDConnect.AcceptAccessTokenScope = ""
99
100         s.testHandler = &Handler{Cluster: cluster}
101         s.testServer = newServerFromIntegrationTestEnv(c)
102         s.testServer.Server.Handler = httpserver.HandlerWithContext(
103                 ctxlog.Context(context.Background(), s.log),
104                 httpserver.AddRequestIDs(httpserver.LogRequests(s.testHandler)))
105         c.Assert(s.testServer.Start(), check.IsNil)
106 }
107
108 func (s *AuthSuite) TestLocalOIDCAccessToken(c *check.C) {
109         req := httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
110         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
111         rr := httptest.NewRecorder()
112         s.testServer.Server.Handler.ServeHTTP(rr, req)
113         resp := rr.Result()
114         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
115         var u arvados.User
116         c.Check(json.NewDecoder(resp.Body).Decode(&u), check.IsNil)
117         c.Check(u.UUID, check.Equals, arvadostest.ActiveUserUUID)
118         c.Check(u.OwnerUUID, check.Equals, "zzzzz-tpzed-000000000000000")
119
120         // Request again to exercise cache.
121         req = httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
122         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
123         rr = httptest.NewRecorder()
124         s.testServer.Server.Handler.ServeHTTP(rr, req)
125         resp = rr.Result()
126         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
127 }