ee267ba5dd8f39bb7ccd219717e69b74f0702265
[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.AcceptAccessTokenScope = "*"
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 }