16306: Merge branch 'master'
[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                 ForceLegacyAPI14: forceLegacyAPI14,
68                 SystemRootToken:  arvadostest.SystemRootToken,
69         }
70         cluster.TLS.Insecure = true
71         cluster.API.MaxItemsPerResponse = 1000
72         cluster.API.MaxRequestAmplification = 4
73         cluster.API.RequestTimeout = arvados.Duration(5 * time.Minute)
74         arvadostest.SetServiceURL(&cluster.Services.RailsAPI, "https://"+os.Getenv("ARVADOS_TEST_API_HOST"))
75         arvadostest.SetServiceURL(&cluster.Services.Controller, "http://localhost/")
76
77         cluster.RemoteClusters = map[string]arvados.RemoteCluster{
78                 "zzzzz": {
79                         Host:   s.remoteServer.Addr,
80                         Proxy:  true,
81                         Scheme: "http",
82                 },
83                 "zmock": {
84                         Host:   s.remoteMock.Addr,
85                         Proxy:  true,
86                         Scheme: "http",
87                 },
88                 "*": {
89                         Scheme: "https",
90                 },
91         }
92         cluster.Login.OpenIDConnect.Enable = true
93         cluster.Login.OpenIDConnect.Issuer = s.fakeProvider.Issuer.URL
94         cluster.Login.OpenIDConnect.ClientID = s.fakeProvider.ValidClientID
95         cluster.Login.OpenIDConnect.ClientSecret = s.fakeProvider.ValidClientSecret
96         cluster.Login.OpenIDConnect.EmailClaim = "email"
97         cluster.Login.OpenIDConnect.EmailVerifiedClaim = "email_verified"
98
99         s.testHandler = &Handler{Cluster: cluster}
100         s.testServer = newServerFromIntegrationTestEnv(c)
101         s.testServer.Server.Handler = httpserver.HandlerWithContext(
102                 ctxlog.Context(context.Background(), s.log),
103                 httpserver.AddRequestIDs(httpserver.LogRequests(s.testHandler)))
104         c.Assert(s.testServer.Start(), check.IsNil)
105 }
106
107 func (s *AuthSuite) TestLocalOIDCAccessToken(c *check.C) {
108         req := httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
109         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
110         rr := httptest.NewRecorder()
111         s.testServer.Server.Handler.ServeHTTP(rr, req)
112         resp := rr.Result()
113         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
114         var u arvados.User
115         c.Check(json.NewDecoder(resp.Body).Decode(&u), check.IsNil)
116         c.Check(u.UUID, check.Equals, arvadostest.ActiveUserUUID)
117         c.Check(u.OwnerUUID, check.Equals, "zzzzz-tpzed-000000000000000")
118
119         // Request again to exercise cache.
120         req = httptest.NewRequest("GET", "/arvados/v1/users/current", nil)
121         req.Header.Set("Authorization", "Bearer "+s.fakeProvider.ValidAccessToken())
122         rr = httptest.NewRecorder()
123         s.testServer.Server.Handler.ServeHTTP(rr, req)
124         resp = rr.Result()
125         c.Check(resp.StatusCode, check.Equals, http.StatusOK)
126 }